ソースを参照

feat(ui): implement emacs-like modeline

Enhanced modeline rendering to show detailed status including: active/inactive visual distinction, modification flags (** vs --), cursor position (Line:Col), scroll percentage (Top/Bot/All/NN%), and major mode. This completes the core UI polish for the GTK frontend.
Bernardo Magri 1 ヶ月 前
コミット
0852851d55
2 ファイル変更40 行追加6 行削除
  1. 1 0
      DEV_STATE.md
  2. 39 6
      src/gtk_editor.cpp

+ 1 - 0
DEV_STATE.md

@@ -75,6 +75,7 @@ Lumacs/
 - ⚠️ **Focus Jumping Partial Fix**: Identified spurious next_window() calls but focus still jumps during typing
 
 - ✅ **Split Ratio Improvement**: Implemented initial split ratio using signal_map with fallback
+- ✅ **Modeline**: Implemented detailed Emacs-like modeline with active/inactive states, flags, percentage, and mode display
 
 ## Todo  
 1. **Phase 7**: Performance optimization and tuning

+ 39 - 6
src/gtk_editor.cpp

@@ -574,14 +574,18 @@ protected:
                                    const Glib::RefPtr<Pango::Layout>& layout, std::shared_ptr<Window> window) {
         if (!core_ || !window) return;
         
+        bool is_active = (window == core_->active_window());
+        
         // Calculate modeline position (second line from bottom)
         double modeline_y = height - (2 * line_height_) - PADDING_BOTTOM;
         double modeline_x = PADDING_LEFT;
         
         // Get theme colors
         auto theme = core_->active_theme();
-        Color bg = theme ? theme->get_bg_color(ThemeElement::StatusLine) : Color(40, 40, 40);
-        Color fg = theme ? theme->get_fg_color(ThemeElement::StatusLine) : Color(200, 200, 200);
+        ThemeElement element = is_active ? ThemeElement::StatusLine : ThemeElement::StatusLineInactive;
+        
+        Color bg = theme ? theme->get_bg_color(element) : (is_active ? Color(60, 60, 60) : Color(40, 40, 40));
+        Color fg = theme ? theme->get_fg_color(element) : (is_active ? Color(220, 220, 220) : Color(160, 160, 160));
         
         // Draw modeline background
         cr->set_source_rgb(bg.r / 255.0, bg.g / 255.0, bg.b / 255.0);
@@ -591,10 +595,39 @@ protected:
         // Build modeline content
         auto cursor = window->cursor();
         auto& buffer = window->buffer();
-        std::string modeline_text = " " + buffer.name() + 
-                                   "    Line " + std::to_string(cursor.line + 1) + 
-                                   ":" + std::to_string(cursor.column + 1) + 
-                                   "    (" + (buffer.is_modified() ? "modified" : "saved") + ")";
+        
+        // 1. Status Flags: ** (modified), -- (saved)
+        std::string flags = buffer.is_modified() ? "**" : "--";
+        
+        // 2. Position Percentage
+        auto [start_line, end_line] = window->visible_line_range();
+        size_t total_lines = buffer.line_count();
+        std::string position;
+        
+        if (total_lines <= 1) {
+            position = "All";
+        } else if (start_line == 0 && end_line >= total_lines) {
+            position = "All";
+        } else if (start_line == 0) {
+            position = "Top";
+        } else if (end_line >= total_lines) {
+            position = "Bot";
+        } else {
+            int percent = static_cast<int>((static_cast<double>(start_line) / total_lines) * 100);
+            position = std::to_string(percent) + "%";
+        }
+
+        // 3. Mode
+        std::string mode = buffer.language();
+        if (mode.empty()) mode = "Fundamental";
+
+        // Format: -**-  Name   (Line, Col)   Pos   (Mode)
+        std::string modeline_text = " -" + flags + "-  " + 
+                                   buffer.name() + 
+                                   "   (" + std::to_string(cursor.line + 1) + 
+                                   "," + std::to_string(cursor.column) + ")" + 
+                                   "   " + position + 
+                                   "   (" + mode + ")";
         
         // Render modeline text
         cr->set_source_rgb(fg.r / 255.0, fg.g / 255.0, fg.b / 255.0);