Author: matt
Date: 2012-07-28 06:38:18 -0700 (Sat, 28 Jul 2012)
New Revision: 9648
Log:
Fluid3: edit labels and widget names right in the tree view. Very comfortable.

Modified:
   branches/branch-3.0/documentation/src/fluid3.dox
   branches/branch-3.0/fluid/Fl_Type.cxx
   branches/branch-3.0/fluid/Fl_Type.h
   branches/branch-3.0/fluid1/Fl_Widget_Type.cxx
   branches/branch-3.0/include/fltk3/MenuWindow.h
   branches/branch-3.0/include/fltk3/Rectangle.h
   branches/branch-3.0/src/fltk3/MenuWindow.cxx
   branches/branch-3.0/src/fltk3/Widget.cxx

Modified: branches/branch-3.0/documentation/src/fluid3.dox
===================================================================
--- branches/branch-3.0/documentation/src/fluid3.dox    2012-07-27 22:12:52 UTC 
(rev 9647)
+++ branches/branch-3.0/documentation/src/fluid3.dox    2012-07-28 13:38:18 UTC 
(rev 9648)
@@ -690,6 +690,10 @@
 "Earlier" and "Later".  This does not affect
 the positions of windows or functions.
 
+When editing a projects, the selected items will be sorted in
+case-sensitive alphabetic order. Holding the Alt key when selecting
+<i>Sort</i> will sort in case-insensitive order.
+
 \par Edit/Earlier (F2)
 
 \par
@@ -710,8 +714,11 @@
 
 \par
 Creates a new Fl_Group and make all the currently
-selected widgets children of it.
+selected widgets children of it. Holding the Alt key when selecting
+this menu item will create a group that is one grid space bigger 
+than the bounding box of all selected widgets.
 
+
 \par Edit/Ungroup (F8)
 
 \par

Modified: branches/branch-3.0/fluid/Fl_Type.cxx
===================================================================
--- branches/branch-3.0/fluid/Fl_Type.cxx       2012-07-27 22:12:52 UTC (rev 
9647)
+++ branches/branch-3.0/fluid/Fl_Type.cxx       2012-07-28 13:38:18 UTC (rev 
9648)
@@ -40,6 +40,7 @@
 #include <fltk3/run.h>
 #include <fltk3/ask.h>
 #include <fltk3/Browser_.h>
+#include <fltk3/MenuWindow.h>
 #include <fltk3/draw.h>
 #include <fltk3/filename.h>
 #include <stdlib.h>
@@ -209,6 +210,10 @@
 class Widget_Browser : public fltk3::Browser_ {
   friend class Fl_Type;
 
+  static void handle_second_single_click_i(void*);
+  
+  Fl_Type* last_clicked;
+  
   // required routines for fltk3::Browser_ subclass:
   void *item_first() const ;
   void *item_next(void *) const ;
@@ -222,6 +227,7 @@
 
 public:        
 
+  void handle_second_single_click();
   int handle(int);
   void callback();
   Widget_Browser(int,int,int,int,const char * =0);
@@ -257,7 +263,7 @@
 : fltk3::Browser_(X,Y,W,H,l) {
   type(fltk3::MULTI_BROWSER);
   Widget::callback(Widget_Browser_callback);
-  when(fltk3::WHEN_RELEASE);
+  when(fltk3::WHEN_RELEASE|fltk3::WHEN_NOT_CHANGED);
 }
 
 void *Widget_Browser::item_first() const {return Fl_Type::first;}
@@ -415,6 +421,7 @@
       W += int(fltk3::width(buf));
     }
   } else {
+    // FIXME: utf8!
     const char* c = l->title();
     char buf[60]; char* p = buf;
     for (int i = 55; i--;) {
@@ -434,14 +441,132 @@
   widget_browser->redraw();
 }
 
+
+extern Fl_Panel* the_panel;
+
+/*
+ This method allow editing simple text inline.
+ 
+ When clicking an already selected editable item, this method will pop up a 
+ small window that allow for quick editing of the item value or label.
+ 
+ Making sure that a second click is not confused with a double click takes
+ some effort in the callback code, causing a timeout, which in turn is canceled
+ by a double click.
+ */
+void Widget_Browser::handle_second_single_click()
+{
+  if (!last_clicked) 
+    return;
+  // find the text that we will edit first
+  const char* text = 0L;
+  if (last_clicked->name()) {
+    text = last_clicked->name();
+  } else if (last_clicked->label()) {
+    text = last_clicked->label();
+  } else {
+    return;
+  }
+  // count the lines in the text
+  int nlines = 1;
+  const char *s = text;
+  while (*s) { if (*s=='\n') nlines++; s++; }
+  if (nlines>10) nlines = 10; 
+  // find the y position of the clicked item (the mouse event is no longer 
reliable)
+  int yp = -position();
+  Fl_Type *t = (Fl_Type*)item_first();
+  while (t && t!=last_clicked) {
+    yp += item_height(t);
+    t = (Fl_Type*)item_next(t);
+  }
+  if (!t) 
+    return;
+  // if the item has a comment, skip that
+  if (t->comment())
+    yp += textsize()-1;
+  // find the x position and width of the name
+  fltk3::font(textfont(), textsize());
+  int xp = x() + fltk3::box_dx(box()) + 3 + 18 + 8 + t->level * 12;
+  if (t->is_widget() || t->is_class()) {
+    const char* c = subclassname(t);
+    if (!strncmp(c,"fltk3::",7)) c += 7;
+    xp += int(fltk3::width(c)+fltk3::width('n'));
+  }
+  // use the widget width minus the x position, but use some minimum width 
+  int wp = w()-xp-fltk3::box_dx(box());
+  if (scrollbar.visible()) wp-=scrollbar_width();
+  if (nlines>1) {
+    if (wp<320) wp = 320;
+  } else {
+    if (wp<200) wp = 200;
+  }
+  int hp = nlines*fltk3::height()+fltk3::DOWN_BOX->dh(); // FIXME: wrap and 
resize if needed
+  // adjust coordinates to global and use a menu window
+  xp += dx_window() + window()->x();
+  yp += dy_window() + window()->y();
+  // open a modal dialog with an input widget
+  fltk3::PopupWindow* w = new fltk3::PopupWindow(xp, yp, wp, hp);
+  fltk3::Input *input = new fltk3::Input(0, 0, wp, hp);
+  if (nlines) input->type(fltk3::MULTILINE_INPUT);
+  input->box(fltk3::DOWN_BOX);
+  input->textfont(textfont());
+  input->textsize(textsize());
+  input->value(text);
+  input->position(0, strlen(input->value()));
+  input->callback(w->hide_i, w);
+  input->when(fltk3::WHEN_ENTER_KEY_ALWAYS);
+  if (w->popup()==input) {
+    int mod = 0;
+    if (strcmp(input->value(), text)) {
+      // FIXME: there are certain illegal characters that must be avoided!
+      if (t->name()) {
+        t->name(input->value());
+      } else if (t->label()) {
+        t->label(input->value());
+      }
+      mod = 1;
+    }
+    redraw_browser();
+    if (mod) {
+      if (the_panel) 
+        Fl_Panel::propagate_load(the_panel);
+      set_modflag(1);
+    }
+  }
+  delete w;
+}
+
+
+void Widget_Browser::handle_second_single_click_i(void* d)
+{
+  ((Widget_Browser*)d)->handle_second_single_click();
+}
+
+
 void Widget_Browser::callback() {
-  selection_changed((Fl_Type*)selection());
+  if (changed()) {
+    // update evrything around the new selection
+    selection_changed((Fl_Type*)selection());
+  } else {
+    // on a single click, we may be able to edit some value directly
+    if ( fltk3::event()==fltk3::RELEASE ) {
+      last_clicked = (Fl_Type*)find_item(fltk3::event_y());
+      if (last_clicked && last_clicked->selected) {
+        // add a timeout to make sure that we have a single click, not a 
double click
+        fltk3::add_timeout(0.5, handle_second_single_click_i, this);      
+      }
+    }
+  }
 }
 
+
 int Widget_Browser::handle(int e) {
   static Fl_Type *title;
   Fl_Type *l;
   int X,Y,W,H; bbox(X,Y,W,H);
+  if (e!=fltk3::MOVE) {
+    fltk3::remove_timeout(handle_second_single_click_i, this);
+  }
   switch (e) {
     case fltk3::PUSH:
       if (!fltk3::event_inside(X,Y,W,H)) break;
@@ -472,8 +597,9 @@
     case fltk3::RELEASE:
       if (!title) {
         l = (Fl_Type*)find_item(fltk3::event_y());
-        if (l && l->new_selected && (fltk3::event_clicks() || 
fltk3::event_state(fltk3::CTRL)))
-          l->open();
+        if (l && l->new_selected && (fltk3::event_clicks() || 
fltk3::event_state(fltk3::CTRL))) {
+            l->open();
+        }
         break;
       }
       l = pushedtitle;
@@ -1869,8 +1995,32 @@
     hide();
 }
 
+extern fltk3::Window* widgetbin_panel;
 
+/**
+ Override show() to make sure that widgets don;t overlap.
+ Specifically, the widget bin and widget panel tend open in the same position. 
+ One panel needs to be moved which interrupts workflow. This function moves
+ the WIdget Panel away from the Widget Bin.
+ */
+void Fl_Panel::show()
+{
+  if (shown()) {
+    // just raise th window, nothing else
+    fltk3::DoubleWindow::show();
+  } else {
+    // show the window, then avoid overlap
+    fltk3::DoubleWindow::show();
+    if (widgetbin_panel && widgetbin_panel->shown()) {
+      if (this->intersects(*widgetbin_panel)) {
+        position(x(), widgetbin_panel->b()+40);
+      }
+    }
+  }
+}
 
+
+
 //
 // End of "$Id$".
 //

Modified: branches/branch-3.0/fluid/Fl_Type.h
===================================================================
--- branches/branch-3.0/fluid/Fl_Type.h 2012-07-27 22:12:52 UTC (rev 9647)
+++ branches/branch-3.0/fluid/Fl_Type.h 2012-07-28 13:38:18 UTC (rev 9648)
@@ -1211,6 +1211,7 @@
   Fl_Panel(int x, int y, int w, int h, const char *name=0L);
   ~Fl_Panel();
   void load(RTTI_Query query);
+  void show(); // override the widget show()
   
   static void *const LOAD;
   static int numselected;

Modified: branches/branch-3.0/fluid1/Fl_Widget_Type.cxx
===================================================================
--- branches/branch-3.0/fluid1/Fl_Widget_Type.cxx       2012-07-27 22:12:52 UTC 
(rev 9647)
+++ branches/branch-3.0/fluid1/Fl_Widget_Type.cxx       2012-07-28 13:38:18 UTC 
(rev 9648)
@@ -1874,7 +1874,16 @@
 void Fl_Widget_Type::open() {
   if (!the_panel) the_panel = make_widget_panel();
   load_panel();
-  if (numselected) the_panel->show();
+  if (numselected) {
+    if (the_panel->visible_r()) {
+      // just pop it to the front
+      the_panel->show();
+    } else {
+      // show the panel and make sure it is not under the widget bin
+      the_panel->show();
+      if (the_panel->con
+    }
+  }
 }
 
 Fl_Type *Fl_Type::current;

Modified: branches/branch-3.0/include/fltk3/MenuWindow.h
===================================================================
--- branches/branch-3.0/include/fltk3/MenuWindow.h      2012-07-27 22:12:52 UTC 
(rev 9647)
+++ branches/branch-3.0/include/fltk3/MenuWindow.h      2012-07-28 13:38:18 UTC 
(rev 9648)
@@ -73,8 +73,24 @@
     
   };
   
+  
+  
+  class PopupWindow : public fltk3::MenuWindow {
+    bool pUserPosition;
+    fltk3::Widget* pTrigger;
+  public:
+    static void hide_i(fltk3::Widget*, void*);
+    int handle(int);
+    PopupWindow(int X, int Y, int W, int H, const char *label = 0);
+    PopupWindow(int W, int H, const char *label = 0);
+    ~PopupWindow();
+    Widget* popup();
+  };
+  
+  
 }
 
+
 #endif
 
 //

Modified: branches/branch-3.0/include/fltk3/Rectangle.h
===================================================================
--- branches/branch-3.0/include/fltk3/Rectangle.h       2012-07-27 22:12:52 UTC 
(rev 9647)
+++ branches/branch-3.0/include/fltk3/Rectangle.h       2012-07-28 13:38:18 UTC 
(rev 9648)
@@ -42,86 +42,89 @@
   class FLTK3_EXPORT Rectangle : public Object {
     
   protected:
-  int x_, y_, w_, h_;
-
- public:
-
-  /*! Left edge */
-  int x() const {return x_;}
-  /*! Top edge */
-  int y() const {return y_;}
-  /*! Distance between left and right edges */
-  int w() const {return w_;}
-  /*! Distance between top and bottom edges */
-  int h() const {return h_;}
-  /*! Return x()+w(), the right edge of the rectangle. */
-  int r() const {return x_+w_;}
-  /*! Return y()+h(), the bottom edge of the rectangle. */
-  int b() const {return y_+h_;}
-  /*! Move the rectangle so the left edge is at \a v. */
-  void x(int v) {x_ = v;}
-  /*! Move the rectangle so the top edge is at \a v. */
-  void y(int v) {y_ = v;}
-  /*! Change w() by moving the right edge. x() does not change. */
-  void w(int v) {w_ = v;}
-  /*! Change h() by moving the bottom edge. y() does not change. */
-  void h(int v) {h_ = v;}
-  /*! Change x() without changing r(), by changing the width. */
-  void set_x(int v) {w_ -= v-x_; x_ = v;}
-  /*! Change y() without changing b(), by changing the height. */
-  void set_y(int v) {h_ -= v-y_; y_ = v;}
-  /*! Change r() without changing x(), by changine the width. */
-  void set_r(int v) {w_ = v-x_;}
-  /*! Change b() without changing y(), by changine the height. */
-  void set_b(int v) {h_ = v-y_;}
-  /*! Set x(), y(), w(), and h() all at once. */
-  void set(int x, int y, int w, int h) {x_=x; y_=y; w_=w; h_=h;}
-  /*! Sets  x, y, w, h so that's it's centered or aligned (if flags!=0) inside 
the source r */
-  void set (const Rectangle& r, int w, int h, int flags = 0);
-  /*! Add \a d to x() without changing r() (it reduces w() by \a d). */
-  void move_x(int d) {x_ += d; w_ -= d;}
-  /*! Add \a d to y() without changing b() (it reduces h() by \a d). */
-  void move_y(int d) {y_ += d; h_ -= d;}
-  /*! Add \a d to r() and w(). */
-  void move_r(int d) {w_ += d;}
-  /*! Add \a d to b() and h(). */
-  void move_b(int d) {h_ += d;}
-  /*! Move all edges in by \a d. See also Symbol::inset() */
-  void inset(int d) {x_ += d; y_ += d; w_ -= 2*d; h_ -= 2*d;}
-  /*! Move entire rectangle by given distance in x and y. */
-  void move(int dx, int dy) {x_ += dx; y_ += dy;}
-  /*! True if w() or h() are less or equal to zero. */
-  bool empty() const {return FLTK3_RECT_EMPTY(w_, h_);}
-  /*! Same as !empty(), true if w() and h() are both greater than zero. */
-  bool not_empty() const {return  !FLTK3_RECT_EMPTY(w_, h_);}
-  /*! Integer center position. Rounded to the left if w() is odd. */
-  int center_x() const {return x_+(w_>>1);}
-  /*! Integer center position. Rounded to lower y if h() is odd. */
-  int center_y() const {return y_+(h_>>1);}
-  /*! Where to put baseline to center current font nicely */
-  int baseline_y() const;
-
-  Rectangle() {}
-
-  /*! Constructor that sets x(), y(), w(), and h(). */
-  Rectangle(int x, int y, int w, int h) : x_(x), y_(y), w_(w), h_(h) {}
-
-  /*! Constructor that sets x() and y() to zero, and sets w() and h(). */
-  Rectangle(int w, int h) : x_(0), y_(0), w_(w), h_(h) {}
-
-  /*! Copy constructor. */
-  Rectangle(const Rectangle& r) : x_(r.x_),y_(r.y_),w_(r.w_),h_(r.h_) {}
-
-  /*! Constructor that calls set(). */
-  Rectangle(const Rectangle& r, int w, int h, int flags = 0) 
{set(r,w,h,flags);}
-
-  /*! True if rectangle contains the pixel who's upper-left corner is at x,y */
-  bool contains(int x, int y) const {return x>=x_ && y>=y_ && x<x_+w_ && 
y<y_+h_;}
-
-  void merge(const Rectangle& r);
-  void intersect(const Rectangle& r);
-
-};
+    int x_, y_, w_, h_;
+    
+  public:
+    
+    /*! Left edge */
+    int x() const {return x_;}
+    /*! Top edge */
+    int y() const {return y_;}
+    /*! Distance between left and right edges */
+    int w() const {return w_;}
+    /*! Distance between top and bottom edges */
+    int h() const {return h_;}
+    /*! Return x()+w(), the right edge of the rectangle. */
+    int r() const {return x_+w_;}
+    /*! Return y()+h(), the bottom edge of the rectangle. */
+    int b() const {return y_+h_;}
+    /*! Move the rectangle so the left edge is at \a v. */
+    void x(int v) {x_ = v;}
+    /*! Move the rectangle so the top edge is at \a v. */
+    void y(int v) {y_ = v;}
+    /*! Change w() by moving the right edge. x() does not change. */
+    void w(int v) {w_ = v;}
+    /*! Change h() by moving the bottom edge. y() does not change. */
+    void h(int v) {h_ = v;}
+    /*! Change x() without changing r(), by changing the width. */
+    void set_x(int v) {w_ -= v-x_; x_ = v;}
+    /*! Change y() without changing b(), by changing the height. */
+    void set_y(int v) {h_ -= v-y_; y_ = v;}
+    /*! Change r() without changing x(), by changine the width. */
+    void set_r(int v) {w_ = v-x_;}
+    /*! Change b() without changing y(), by changine the height. */
+    void set_b(int v) {h_ = v-y_;}
+    /*! Set x(), y(), w(), and h() all at once. */
+    void set(int x, int y, int w, int h) {x_=x; y_=y; w_=w; h_=h;}
+    /*! Sets  x, y, w, h so that's it's centered or aligned (if flags!=0) 
inside the source r */
+    void set (const Rectangle& r, int w, int h, int flags = 0);
+    /*! Add \a d to x() without changing r() (it reduces w() by \a d). */
+    void move_x(int d) {x_ += d; w_ -= d;}
+    /*! Add \a d to y() without changing b() (it reduces h() by \a d). */
+    void move_y(int d) {y_ += d; h_ -= d;}
+    /*! Add \a d to r() and w(). */
+    void move_r(int d) {w_ += d;}
+    /*! Add \a d to b() and h(). */
+    void move_b(int d) {h_ += d;}
+    /*! Move all edges in by \a d. See also Symbol::inset() */
+    void inset(int d) {x_ += d; y_ += d; w_ -= 2*d; h_ -= 2*d;}
+    /*! Move entire rectangle by given distance in x and y. */
+    void move(int dx, int dy) {x_ += dx; y_ += dy;}
+    /*! True if w() or h() are less or equal to zero. */
+    bool empty() const {return FLTK3_RECT_EMPTY(w_, h_);}
+    /*! Same as !empty(), true if w() and h() are both greater than zero. */
+    bool not_empty() const {return  !FLTK3_RECT_EMPTY(w_, h_);}
+    /*! Integer center position. Rounded to the left if w() is odd. */
+    int center_x() const {return x_+(w_>>1);}
+    /*! Integer center position. Rounded to lower y if h() is odd. */
+    int center_y() const {return y_+(h_>>1);}
+    /*! Where to put baseline to center current font nicely */
+    int baseline_y() const;
+    
+    Rectangle() {}
+    
+    /*! Constructor that sets x(), y(), w(), and h(). */
+    Rectangle(int x, int y, int w, int h) : x_(x), y_(y), w_(w), h_(h) {}
+    
+    /*! Constructor that sets x() and y() to zero, and sets w() and h(). */
+    Rectangle(int w, int h) : x_(0), y_(0), w_(w), h_(h) {}
+    
+    /*! Copy constructor. */
+    Rectangle(const Rectangle& r) : x_(r.x_),y_(r.y_),w_(r.w_),h_(r.h_) {}
+    
+    /*! Constructor that calls set(). */
+    Rectangle(const Rectangle& r, int w, int h, int flags = 0) 
{set(r,w,h,flags);}
+    
+    /*! True if rectangle contains the pixel who's upper-left corner is at x,y 
*/
+    bool contains(int x, int y) const {return x>=x_ && y>=y_ && x<x_+w_ && 
y<y_+h_;}
+    
+    void merge(const Rectangle& r);
+    void intersect(const Rectangle& r);
+    
+    /*! True if two rectangles touch or intersect. */
+    bool intersects(const Rectangle& r);
+    
+  };
   
 }
 

Modified: branches/branch-3.0/src/fltk3/MenuWindow.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/MenuWindow.cxx        2012-07-27 22:12:52 UTC 
(rev 9647)
+++ branches/branch-3.0/src/fltk3/MenuWindow.cxx        2012-07-28 13:38:18 UTC 
(rev 9648)
@@ -119,6 +119,99 @@
 }
 
 
+//------------------------------------------------------------------------------
+
+
+fltk3::PopupWindow::PopupWindow(int x, int y, int w, int h, const char *title)
+: fltk3::MenuWindow(x, y, w, h, title),
+  pUserPosition(true)
+{
+  set_modal();
+  clear_border();
+  set_menu_window();
+}
+
+
+fltk3::PopupWindow::PopupWindow(int w, int h, const char *title)
+: fltk3::MenuWindow(w, h, title),
+  pUserPosition(false)
+{
+  set_modal();
+  clear_border();
+  set_menu_window();
+}
+
+
+fltk3::PopupWindow::~PopupWindow()
+{
+  hide();
+}
+
+
+void fltk3::PopupWindow::hide_i(fltk3::Widget* w, void *d)
+{
+  fltk3::PopupWindow* p = ((fltk3::PopupWindow*)d);
+  p->pTrigger = w;
+  p->hide();
+}
+
+
+int fltk3::PopupWindow::handle(int e) {
+  fltk3::Widget* wi;
+  switch (e) {
+    case fltk3::KEYBOARD:
+      switch (fltk3::event_key()) {
+        case fltk3::EscapeKey:
+          pTrigger = 0L;
+          hide();
+          return 1;
+      }
+      for (wi = fltk3::focus(); wi; wi = wi->parent()) {
+        if (wi==this) break;
+        if (wi->send(fltk3::KEYBOARD)) return 1;
+      }
+      return 0;
+    case fltk3::SHORTCUT: 
+      switch (fltk3::event_key()) {
+        case fltk3::EscapeKey:
+          pTrigger = 0L;
+          hide();
+          return 1;
+      }
+      break;
+    case fltk3::PUSH: {
+      int mx = fltk3::event_x_root();
+      int my = fltk3::event_y_root();
+      if (!Rectangle::contains(mx, my)) {
+        pTrigger = 0L;
+        hide();
+        return 1;
+      }
+      break;
+    }
+  }
+  return MenuWindow::handle(e);
+}
+
+
+fltk3::Widget* fltk3::PopupWindow::popup()
+{
+  pTrigger = 0L;
+  if (!pUserPosition)
+    position(fltk3::event_x_root(), fltk3::event_y_root());
+  show();
+  fltk3::grab(this);
+  for (;;) {
+    fltk3::wait();
+    if (!visible_r()) 
+      break;
+  }
+  hide();
+  fltk3::grab(0);
+  return pTrigger;
+}
+
+
 //
 // End of "$Id$".
 //

Modified: branches/branch-3.0/src/fltk3/Widget.cxx
===================================================================
--- branches/branch-3.0/src/fltk3/Widget.cxx    2012-07-27 22:12:52 UTC (rev 
9647)
+++ branches/branch-3.0/src/fltk3/Widget.cxx    2012-07-28 13:38:18 UTC (rev 
9648)
@@ -509,7 +509,13 @@
   if (R.b() < b()) set_b(R.b());
 }
 
+bool fltk3::Rectangle::intersects(const fltk3::Rectangle& R) {
+  if (R.x()>r() || R.r()<x()) return false;
+  if (R.y()>b() || R.b()<y()) return false;
+  return true;
+}
 
+
 // Call to->handle(), but first replace the mouse x/y with the correct
 // values to account for nested windows. 'window' is the outermost
 // window the event was posted to by the system

_______________________________________________
fltk-commit mailing list
[email protected]
http://lists.easysw.com/mailman/listinfo/fltk-commit

Reply via email to