/[svn]/gigedit/trunk/src/dimregionchooser.cpp
ViewVC logotype

Diff of /gigedit/trunk/src/dimregionchooser.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1077 by persson, Tue Mar 6 18:34:47 2007 UTC revision 1103 by persson, Sun Mar 18 07:26:43 2007 UTC
# Line 18  Line 18 
18   */   */
19    
20  #include "dimregionchooser.h"  #include "dimregionchooser.h"
21    #include <gdkmm/cursor.h>
22    
23  DimRegionChooser::DimRegionChooser()  DimRegionChooser::DimRegionChooser()
24  {  {
# Line 40  DimRegionChooser::DimRegionChooser() Line 41  DimRegionChooser::DimRegionChooser()
41      region = 0;      region = 0;
42      dimregno = -1;      dimregno = -1;
43      focus_line = 0;      focus_line = 0;
44        resize.active = false;
45        cursor_is_resize = false;
46        h = 20;
47        w = 800;
48      set_flags(Gtk::CAN_FOCUS);      set_flags(Gtk::CAN_FOCUS);
49      add_events(Gdk::BUTTON_PRESS_MASK);      add_events(Gdk::BUTTON_PRESS_MASK | Gdk::POINTER_MOTION_MASK |
50                   Gdk::POINTER_MOTION_HINT_MASK);
51    
52      for (int i = 0 ; i < 256 ; i++) {      for (int i = 0 ; i < 256 ; i++) {
53          dimvalue_from[i] = 0;          dimvalue_from[i] = 0;
# Line 74  bool DimRegionChooser::on_expose_event(G Line 80  bool DimRegionChooser::on_expose_event(G
80      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);      Glib::RefPtr<Pango::Layout> layout = Pango::Layout::create(context);
81    
82      window->clear();      window->clear();
     const int h = 20;  
     const int w = 800;  
     const int w1 = 100;  
83      int y = 0;      int y = 0;
84      int bitpos = 0;      double maxwidth = 0;
85      for (int i = 0 ; i < region->Dimensions ; i++) {      for (int i = 0 ; i < region->Dimensions ; i++) {
86    
87          int nbZones = region->pDimensionDefinitions[i].zones;          int nbZones = region->pDimensionDefinitions[i].zones;
# Line 129  bool DimRegionChooser::on_expose_event(G Line 132  bool DimRegionChooser::on_expose_event(G
132              layout->set_text(dstr);              layout->set_text(dstr);
133    
134              Pango::Rectangle rectangle = layout->get_logical_extents();              Pango::Rectangle rectangle = layout->get_logical_extents();
135                double text_w = double(rectangle.get_width()) / Pango::SCALE;
136                if (text_w > maxwidth) maxwidth = text_w;
137              double text_h = double(rectangle.get_height()) / Pango::SCALE;              double text_h = double(rectangle.get_height()) / Pango::SCALE;
138              Glib::RefPtr<const Gdk::GC> fg = get_style()->get_fg_gc(get_state());              Glib::RefPtr<const Gdk::GC> fg = get_style()->get_fg_gc(get_state());
139              window->draw_layout(fg, 4, int(y + (h - text_h) / 2 + 0.5), layout);              window->draw_layout(fg, 4, int(y + (h - text_h) / 2 + 0.5), layout);
140    
141            }
142            y += h;
143        }
144        y = 0;
145        int bitpos = 0;
146        label_width = int(maxwidth + 10);
147        for (int i = 0 ; i < region->Dimensions ; i++) {
148            int nbZones = region->pDimensionDefinitions[i].zones;
149            if (nbZones) {
150    
151              if (has_focus() && focus_line == i) {              if (has_focus() && focus_line == i) {
152                  Gdk::Rectangle farea(0, y, 50, 20);                  Gdk::Rectangle farea(0, y, 150, 20);
153                  get_style()->paint_focus(window, get_state(), farea, *this, "hejsan", 0, y, 50, 20);                  get_style()->paint_focus(window, get_state(), farea, *this, "",
154                                             0, y, label_width, 20);
155              }              }
156    
157              Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();              Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
158              window->draw_line(black, w1, y, w - 1, y);              window->draw_line(black, label_width, y, w - 1, y);
159              window->draw_line(black, w - 1, y + h - 1, w1, y + h - 1);              window->draw_line(black, w - 1, y + h - 1, label_width, y + h - 1);
160              window->draw_rectangle(get_style()->get_white_gc(), true, w1 + 1, y + 1, (w - w1 - 2), h - 2);              window->draw_rectangle(get_style()->get_white_gc(), true,
161                                       label_width + 1, y + 1, (w - label_width - 2), h - 2);
162    
163              int c = 0;              int c = 0;
164              if (dimregno >= 0) {              if (dimregno >= 0) {
# Line 155  bool DimRegionChooser::on_expose_event(G Line 172  bool DimRegionChooser::on_expose_event(G
172                   region->pDimensionRegions[c]->VelocityUpperLimit));                   region->pDimensionRegions[c]->VelocityUpperLimit));
173    
174              if (customsplits) {              if (customsplits) {
175                  window->draw_line(black, w1, y + 1, w1, y + h - 2);                  window->draw_line(black, label_width, y + 1, label_width, y + h - 2);
176                  for (int j = 0 ; j < nbZones ; j++) {                  for (int j = 0 ; j < nbZones ; j++) {
177                      gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];                      gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];
178                      int upperLimit = d->DimensionUpperLimits[i];                      int upperLimit = d->DimensionUpperLimits[i];
179                      if (!upperLimit) upperLimit = d->VelocityUpperLimit;                      if (!upperLimit) upperLimit = d->VelocityUpperLimit;
180                      int v = upperLimit + 1;                      int v = upperLimit + 1;
181                      int x = int((w - w1 - 1) * v / 128.0 + 0.5);                      int x = int((w - label_width - 1) * v / 128.0 + 0.5);
182                      window->draw_line(black, w1 + x, y + 1, w1 + x, y + h - 2);                      window->draw_line(black, label_width + x, y + 1, label_width + x, y + h - 2);
183                  }                  }
184              } else {              } else {
185                  for (int j = 0 ; j <= nbZones ; j++) {                  for (int j = 0 ; j <= nbZones ; j++) {
186                      int x = int((w - w1 - 1) * j / double(nbZones) + 0.5);                      int x = int((w - label_width - 1) * j / double(nbZones) + 0.5);
187                      window->draw_line(black, w1 + x, y + 1, w1 + x, y + h - 2);                      window->draw_line(black, label_width + x, y + 1, label_width + x, y + h - 2);
188                  }                  }
189              }              }
190    
# Line 181  bool DimRegionChooser::on_expose_event(G Line 198  bool DimRegionChooser::on_expose_event(G
198                          int upperLimit = d->DimensionUpperLimits[i];                          int upperLimit = d->DimensionUpperLimits[i];
199                          if (!upperLimit) upperLimit = d->VelocityUpperLimit;                          if (!upperLimit) upperLimit = d->VelocityUpperLimit;
200                          int v = upperLimit + 1;                          int v = upperLimit + 1;
201                          int x2 = int((w - w1 - 1) * v / 128.0 + 0.5);                          int x2 = int((w - label_width - 1) * v / 128.0 + 0.5);
202                          if (j == dr && x1 < x2) {                          if (j == dr && x1 < x2) {
203                              window->draw_rectangle(gc, true, w1 + x1 + 1, y + 1, (x2 - x1) - 1, h - 2);                              window->draw_rectangle(gc, true, label_width + x1 + 1, y + 1,
204                                                       (x2 - x1) - 1, h - 2);
205                              break;                              break;
206                          }                          }
207                          x1 = x2;                          x1 = x2;
208                      }                      }
209                  } else {                  } else {
210                      if (dr < nbZones) {                      if (dr < nbZones) {
211                          int x1 = int((w - w1 - 1) * dr / double(nbZones) + 0.5);                          int x1 = int((w - label_width - 1) * dr / double(nbZones) + 0.5);
212                          int x2 = int((w - w1 - 1) * (dr + 1) / double(nbZones) + 0.5);                          int x2 = int((w - label_width - 1) * (dr + 1) / double(nbZones) + 0.5);
213                          window->draw_rectangle(gc, true, w1 + x1 + 1, y + 1, (x2 - x1) - 1, h - 2);                          window->draw_rectangle(gc, true, label_width + x1 + 1, y + 1,
214                                                   (x2 - x1) - 1, h - 2);
215                      }                      }
216                  }                  }
217              }              }
# Line 205  bool DimRegionChooser::on_expose_event(G Line 224  bool DimRegionChooser::on_expose_event(G
224      return true;      return true;
225  }  }
226    
   
227  void DimRegionChooser::on_size_request(GtkRequisition* requisition)  void DimRegionChooser::on_size_request(GtkRequisition* requisition)
228  {  {
229      printf("DimRegionChooser::on_size_request\n");      printf("DimRegionChooser::on_size_request\n");
230      *requisition = GtkRequisition();      *requisition = GtkRequisition();
231      requisition->height = region ? region->Dimensions * 20 : 0;      requisition->height = region ? nbDimensions * 20 : 0;
232      requisition->width = 800;      requisition->width = 800;
233  }  }
234    
# Line 227  void DimRegionChooser::set_region(gig::R Line 245  void DimRegionChooser::set_region(gig::R
245      this->region = region;      this->region = region;
246      dimregno = 0;      dimregno = 0;
247      int bitcount = 0;      int bitcount = 0;
248      for (int dim = 0 ; dim < region->Dimensions ; dim++) {      nbDimensions = 0;
249          int from = dimvalue_from[region->pDimensionDefinitions[dim].dimension];      if (region) {
250          int to = dimvalue_to[region->pDimensionDefinitions[dim].dimension];          for (int dim = 0 ; dim < region->Dimensions ; dim++) {
251          int z;              if (region->pDimensionDefinitions[dim].bits == 0) continue;
252          switch (region->pDimensionDefinitions[dim].split_type) {              nbDimensions++;
253          case gig::split_type_normal:  
254              z = int((to + from) / 2.0 / region->pDimensionDefinitions[dim].zone_size);              int from = dimvalue_from[region->pDimensionDefinitions[dim].dimension];
255              break;              int to = dimvalue_to[region->pDimensionDefinitions[dim].dimension];
256          case gig::split_type_bit:              int z;
257              z = std::min(from, region->pDimensionDefinitions[dim].zones - 1);              switch (region->pDimensionDefinitions[dim].split_type) {
258              break;              case gig::split_type_normal:
259          }                  z = int((to + from) / 2.0 / region->pDimensionDefinitions[dim].zone_size);
260          int mask =                  break;
261              ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) <<              case gig::split_type_bit:
262                bitcount);                  z = std::min(from, region->pDimensionDefinitions[dim].zones - 1);
263          dimregno &= mask;                  break;
264          dimregno |= (z << bitcount);              }
265          bitcount += region->pDimensionDefinitions[dim].bits;              int mask =
266                    ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) <<
267                      bitcount);
268                dimregno &= mask;
269                dimregno |= (z << bitcount);
270                bitcount += region->pDimensionDefinitions[dim].bits;
271            }
272            dimreg = region->pDimensionRegions[dimregno];
273      }      }
     dimreg = region->pDimensionRegions[dimregno];  
274      sel_changed_signal.emit();      sel_changed_signal.emit();
275      queue_resize();      queue_resize();
276  }  }
# Line 258  void DimRegionChooser::set_region(gig::R Line 282  void DimRegionChooser::set_region(gig::R
282    }    }
283  */  */
284    
285  bool DimRegionChooser::on_button_press_event(GdkEventButton* event)  bool DimRegionChooser::on_button_release_event(GdkEventButton* event)
286  {  {
287      const int h = 20;      if (resize.active) {
288      const int w = 800;          get_window()->pointer_ungrab(event->time);
289      const int w1 = 100;          resize.active = false;
290    
291      if (region) {          if (region->pDimensionDefinitions[resize.dimension].dimension == gig::dimension_velocity) {
292          if (event->y < region->Dimensions * h &&  
293              event->x >= w1 && event->x < w) {              int bitpos = 0;
294                for (int j = 0 ; j < resize.dimension ; j++) {
295                    bitpos += region->pDimensionDefinitions[j].bits;
296                }
297                int mask =
298                         ~(((1 << region->pDimensionDefinitions[resize.dimension].bits) - 1) << bitpos);
299                int c = dimregno & mask; // mask away this dimension
300    
301                gig::DimensionRegion *d = region->pDimensionRegions[c + resize.offset];
302                if (d->DimensionUpperLimits[resize.dimension]) {
303                    d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
304                } else {
305                    d->VelocityUpperLimit = resize.pos - 1;
306                }
307    
308            } else {
309                for (int i = 0 ; i < region->DimensionRegions ; ) {
310    
311                    gig::DimensionRegion *d = region->pDimensionRegions[i + resize.offset];
312                    d->DimensionUpperLimits[resize.dimension] = resize.pos - 1;
313    
314                    int bitpos = 0;
315                    int j;
316                    for (j = 0 ; j < region->Dimensions ; j++) {
317                        if (j != resize.dimension) {
318                            int maxzones = 1 << region->pDimensionDefinitions[j].bits;
319                            int dimj = (i >> bitpos) & (maxzones - 1);
320                            if (dimj + 1 < region->pDimensionDefinitions[j].zones) break;
321                        }
322                        bitpos += region->pDimensionDefinitions[j].bits;
323                    }
324                    if (j == region->Dimensions) break;
325                    i = (i & ~((1 << bitpos) - 1)) + (1 << bitpos);
326                }
327            }
328    
329            if (!is_in_resize_zone(event->x, event->y) && cursor_is_resize) {
330                get_window()->set_cursor();
331                cursor_is_resize = false;
332            }
333        }
334        return true;
335    }
336    
337    bool DimRegionChooser::on_button_press_event(GdkEventButton* event)
338    {
339        if (region && event->y < nbDimensions * h &&
340            event->x >= label_width && event->x < w) {
341    
342              int dim = int(event->y / h);          if (is_in_resize_zone(event->x, event->y)) {
343                Gdk::Cursor double_arrow(Gdk::SB_H_DOUBLE_ARROW);
344                get_window()->pointer_grab(false,
345                                           Gdk::BUTTON_RELEASE_MASK |
346                                           Gdk::POINTER_MOTION_MASK |
347                                           Gdk::POINTER_MOTION_HINT_MASK,
348                                           double_arrow, event->time);
349                resize.active = true;
350            } else {
351                int ydim = int(event->y / h);
352                int dim;
353                for (dim = 0 ; dim < region->Dimensions ; dim++) {
354                    if (region->pDimensionDefinitions[dim].bits == 0) continue;
355                    if (ydim == 0) break;
356                    ydim--;
357                }
358              int nbZones = region->pDimensionDefinitions[dim].zones;              int nbZones = region->pDimensionDefinitions[dim].zones;
359    
360              int z = -1;              int z = -1;
# Line 288  bool DimRegionChooser::on_button_press_e Line 374  bool DimRegionChooser::on_button_press_e
374                   (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&                   (region->pDimensionDefinitions[i].dimension == gig::dimension_velocity &&
375                    region->pDimensionRegions[c]->VelocityUpperLimit));                    region->pDimensionRegions[c]->VelocityUpperLimit));
376              if (customsplits) {              if (customsplits) {
377                  int val = int((event->x - w1) * 128 / (w - w1 - 1));                  int val = int((event->x - label_width) * 128 / (w - label_width - 1));
378    
379                  if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {                  if (region->pDimensionRegions[c]->DimensionUpperLimits[i]) {
380                      for (z = 0 ; z < nbZones ; z++) {                      for (z = 0 ; z < nbZones ; z++) {
# Line 302  bool DimRegionChooser::on_button_press_e Line 388  bool DimRegionChooser::on_button_press_e
388                      }                      }
389                  }                  }
390              } else {              } else {
391                  z = int((event->x - w1) * nbZones / (w - w1 - 1));                  z = int((event->x - label_width) * nbZones / (w - label_width - 1));
392              }              }
393    
394              printf("dim=%d z=%d dimensionsource=%d split_type=%d zones=%d zone_size=%f\n", dim, z,              printf("dim=%d z=%d dimensionsource=%d split_type=%d zones=%d zone_size=%f\n", dim, z,
# Line 337  bool DimRegionChooser::on_button_press_e Line 423  bool DimRegionChooser::on_button_press_e
423      return true;      return true;
424  }  }
425    
426    bool DimRegionChooser::on_motion_notify_event(GdkEventMotion* event)
427    {
428        Glib::RefPtr<Gdk::Window> window = get_window();
429        int x, y;
430        Gdk::ModifierType state = Gdk::ModifierType(0);
431        window->get_pointer(x, y, state);
432    
433        if (resize.active) {
434            int k = int((x - label_width) * 128.0 / (w - label_width - 1) + 0.5);
435    
436            if (k < resize.min) k = resize.min;
437            else if (k > resize.max) k = resize.max;
438    
439            if (k < 2) k = 2; // k is upper limit + 1, upper limit 0 is forbidden
440    
441            if (k != resize.pos) {
442                Glib::RefPtr<const Gdk::GC> black = get_style()->get_black_gc();
443                Glib::RefPtr<const Gdk::GC> white = get_style()->get_white_gc();
444    
445                int prevx = int((w - label_width - 1) * resize.pos / 128.0 + 0.5) + label_width;
446                int x = int((w - label_width - 1) * k / 128.0 + 0.5) + label_width;
447                int y = resize.dimension * h;
448    
449                if (resize.selected == resize.none) {
450                    if (resize.pos != resize.min && resize.pos != resize.max) {
451                        window->draw_line(white, prevx, y + 1, prevx, y + h - 2);
452                    }
453                } else {
454                    gc->set_foreground(red);
455    
456                    Glib::RefPtr<const Gdk::GC> left;
457                    Glib::RefPtr<const Gdk::GC> right;
458                    if (resize.selected == resize.left) {
459                        left = gc;
460                        right = white;
461                    } else {
462                        left = white;
463                        right = gc;
464                    }
465    
466                    if (k > resize.pos) {
467                        int xx = resize.pos == resize.min ? 1 : 0;
468                        window->draw_rectangle(left, true,
469                                               prevx + xx, y + 1, x - prevx - xx, h - 2);
470                    } else {
471                        int xx = resize.pos == resize.max ? 0 : 1;
472                        window->draw_rectangle(right, true,
473                                               x, y + 1, prevx - x + xx, h - 2);
474                    }
475                }
476                window->draw_line(black, x, y + 1, x, y + h - 2);
477                resize.pos = k;
478            }
479        } else {
480            if (is_in_resize_zone(x, y)) {
481                if (!cursor_is_resize) {
482                    Gdk::Cursor double_arrow(Gdk::SB_H_DOUBLE_ARROW);
483                    window->set_cursor(double_arrow);
484                    cursor_is_resize = true;
485                }
486            } else if (cursor_is_resize) {
487                window->set_cursor();
488                cursor_is_resize = false;
489            }
490        }
491        return true;
492    }
493    
494    bool DimRegionChooser::is_in_resize_zone(double x, double y)
495    {
496        if (region && y < nbDimensions * h && x >= label_width && x < w) {
497            int ydim = int(y / h);
498            int dim;
499            int bitpos = 0;
500            for (dim = 0 ; dim < region->Dimensions ; dim++) {
501                if (region->pDimensionDefinitions[dim].bits == 0) continue;
502                if (ydim == 0) break;
503                ydim--;
504                bitpos += region->pDimensionDefinitions[dim].bits;
505            }
506            int nbZones = region->pDimensionDefinitions[dim].zones;
507    
508            int c = 0;
509            if (dimregno >= 0) {
510                int mask = ~(((1 << region->pDimensionDefinitions[dim].bits) - 1) << bitpos);
511                c = dimregno & mask; // mask away this dimension
512            }
513            bool customsplits =
514                ((region->pDimensionDefinitions[dim].split_type == gig::split_type_normal &&
515                  region->pDimensionRegions[c]->DimensionUpperLimits[dim]) ||
516                 (region->pDimensionDefinitions[dim].dimension == gig::dimension_velocity &&
517                  region->pDimensionRegions[c]->VelocityUpperLimit));
518    
519            if (customsplits) {
520                int prev_limit = 0;
521                for (int j = 0 ; j < nbZones - 1 ; j++) {
522                    gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];
523                    int upperLimit = d->DimensionUpperLimits[dim];
524                    if (!upperLimit) upperLimit = d->VelocityUpperLimit;
525                    int limit = upperLimit + 1;
526                    int limitx = int((w - label_width - 1) * limit / 128.0 + 0.5) + label_width;
527    
528                    if (x <= limitx - 2) break;
529                    if (x <= limitx + 2) {
530                        resize.dimension = dim;
531                        resize.offset = j << bitpos;
532                        resize.pos = limit;
533                        resize.min = prev_limit;
534    
535                        int dr = (dimregno >> bitpos) &
536                            ((1 << region->pDimensionDefinitions[dim].bits) - 1);
537                        resize.selected = dr == j ? resize.left :
538                            dr == j + 1 ? resize.right : resize.none;
539    
540                        j++;
541                        gig::DimensionRegion *d = region->pDimensionRegions[c + (j << bitpos)];
542                        int upperLimit = d->DimensionUpperLimits[dim];
543                        if (!upperLimit) upperLimit = d->VelocityUpperLimit;
544                        int limit = upperLimit + 1;
545                        resize.max = limit;
546                        return true;
547                    }
548                    prev_limit = limit;
549                }
550            }
551        }
552        return false;
553    }
554    
555  sigc::signal<void> DimRegionChooser::signal_sel_changed()  sigc::signal<void> DimRegionChooser::signal_sel_changed()
556  {  {
557      return sel_changed_signal;      return sel_changed_signal;

Legend:
Removed from v.1077  
changed lines
  Added in v.1103

  ViewVC Help
Powered by ViewVC