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

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

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

revision 3105 by schoenebeck, Fri Feb 10 18:40:26 2017 UTC revision 3134 by schoenebeck, Fri Apr 28 12:41:12 2017 UTC
# Line 20  Line 20 
20  #include <gtkmm/box.h>  #include <gtkmm/box.h>
21  #include "dimregionchooser.h"  #include "dimregionchooser.h"
22  #include <cairomm/context.h>  #include <cairomm/context.h>
23    #include <cairomm/surface.h>
24  #include <gdkmm/cursor.h>  #include <gdkmm/cursor.h>
25  #include <gdkmm/general.h>  #include <gdkmm/general.h>
26  #include <glibmm/stringutils.h>  #include <glibmm/stringutils.h>
# Line 28  Line 29 
29  #include <assert.h>  #include <assert.h>
30    
31  #include "global.h"  #include "global.h"
32    #include "gfx/builtinpix.h"
33    
34  // taken from gdk/gdkkeysyms.h  //TODO: this function and dimensionCaseOf() from global.h are duplicates, eliminate either one of them!
35  // (define on demand, to avoid unnecessary dev lib package build dependency)  static DimensionCase caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {
36  #ifndef GDK_KEY_Control_L      DimensionCase dimCase;
 # define GDK_KEY_Control_L 0xffe3  
 #endif  
 #ifndef GDK_KEY_Control_R  
 # define GDK_KEY_Control_R 0xffe4  
 #endif  
   
 static std::map<gig::dimension_t,int> caseOfDimRegion(gig::DimensionRegion* dr, bool* isValidZone) {  
     std::map<gig::dimension_t,int> dimCase;  
37      if (!dr) {      if (!dr) {
38          *isValidZone = false;          *isValidZone = false;
39          return dimCase;          return dimCase;
# Line 57  static std::map<gig::dimension_t,int> ca Line 51  static std::map<gig::dimension_t,int> ca
51      if (drIndex == 256) {      if (drIndex == 256) {
52          fprintf(stderr, "DimRegionChooser: ERROR: index of dim region not found!\n");          fprintf(stderr, "DimRegionChooser: ERROR: index of dim region not found!\n");
53          *isValidZone = false;          *isValidZone = false;
54          return std::map<gig::dimension_t,int>();          return DimensionCase();
55      }      }
56    
57      for (int d = 0, baseBits = 0; d < rgn->Dimensions; ++d) {      for (int d = 0, baseBits = 0; d < rgn->Dimensions; ++d) {
# Line 68  static std::map<gig::dimension_t,int> ca Line 62  static std::map<gig::dimension_t,int> ca
62          // there are also DimensionRegion objects of unused zones, skip them          // there are also DimensionRegion objects of unused zones, skip them
63          if (dimCase[rgn->pDimensionDefinitions[d].dimension] >= rgn->pDimensionDefinitions[d].zones) {          if (dimCase[rgn->pDimensionDefinitions[d].dimension] >= rgn->pDimensionDefinitions[d].zones) {
64              *isValidZone = false;              *isValidZone = false;
65              return std::map<gig::dimension_t,int>();              return DimensionCase();
66          }          }
67      }      }
68    
# Line 77  static std::map<gig::dimension_t,int> ca Line 71  static std::map<gig::dimension_t,int> ca
71  }  }
72    
73  DimRegionChooser::DimRegionChooser(Gtk::Window& window) :  DimRegionChooser::DimRegionChooser(Gtk::Window& window) :
74      red("#8070ff"),      red("#ff476e"),
75        blue("#4796ff"),
76      black("black"),      black("black"),
77      white("white")      white("white")
78  {  {
79        // make sure blue hatched pattern pixmap is loaded
80        loadBuiltInPix();
81    
82        // create blue hatched pattern
83        {
84            const int width = blueHatchedPattern->get_width();
85            const int height = blueHatchedPattern->get_height();
86            const int stride = blueHatchedPattern->get_rowstride();
87    
88            // manually convert from RGBA to ARGB
89            this->blueHatchedPatternARGB = blueHatchedPattern->copy();
90            const int pixelSize = stride / width;
91            const int totalPixels = width * height;
92            assert(pixelSize == 4);
93            unsigned char* ptr = this->blueHatchedPatternARGB->get_pixels();
94            for (int iPixel = 0; iPixel < totalPixels; ++iPixel, ptr += pixelSize) {
95                const unsigned char r = ptr[0];
96                const unsigned char g = ptr[1];
97                const unsigned char b = ptr[2];
98                const unsigned char a = ptr[3];
99                ptr[0] = b;
100                ptr[1] = g;
101                ptr[2] = r;
102                ptr[3] = a;
103            }
104    
105            Cairo::RefPtr<Cairo::ImageSurface> imageSurface = Cairo::ImageSurface::create(
106                this->blueHatchedPatternARGB->get_pixels(), Cairo::FORMAT_ARGB32, width, height, stride
107            );
108            this->blueHatchedSurfacePattern = Cairo::SurfacePattern::create(imageSurface);
109            this->blueHatchedSurfacePattern->set_extend(Cairo::EXTEND_REPEAT);
110        }
111    
112      instrument = 0;      instrument = 0;
113      region = 0;      region = 0;
114      maindimregno = -1;      maindimregno = -1;
115        maindimtype = gig::dimension_none; // initialize with invalid dimension type
116      focus_line = 0;      focus_line = 0;
117      resize.active = false;      resize.active = false;
118      cursor_is_resize = false;      cursor_is_resize = false;
119      h = 24;      h = 24;
120      multiSelectKeyDown = false;      multiSelectKeyDown = false;
121        primaryKeyDown = false;
122        shiftKeyDown = false;
123      modifybothchannels = modifyalldimregs = modifybothchannels = false;      modifybothchannels = modifyalldimregs = modifybothchannels = false;
124      set_can_focus();      set_can_focus();
125    
# Line 253  bool DimRegionChooser::on_draw(const Cai Line 284  bool DimRegionChooser::on_draw(const Cai
284                      dstr = dstrbuf;                      dstr = dstrbuf;
285                      break;                      break;
286                  }                  }
                 layout->set_text(dstr);  
287    
288                    // Since bold font yields in larger label width, we first always
289                    // set the bold text variant, retrieve its dimensions (as worst
290                    // case dimensions of the label) ...
291                    layout->set_markup("<b>" + Glib::ustring(dstr) + "</b>");
292                  Pango::Rectangle rectangle = layout->get_logical_extents();                  Pango::Rectangle rectangle = layout->get_logical_extents();
293                    // ... and then reset the label to regular font style in case
294                    // the line is not selected. Otherwise the right hand side
295                    // actual dimension zones would jump around on selection change.
296                    bool isSelectedLine = (focus_line == i);
297                    if (!isSelectedLine)
298                        layout->set_markup(dstr);
299    
300                  double text_w = double(rectangle.get_width()) / Pango::SCALE;                  double text_w = double(rectangle.get_width()) / Pango::SCALE;
301                  if (text_w > maxwidth) maxwidth = text_w;                  if (text_w > maxwidth) maxwidth = text_w;
302    
# Line 362  bool DimRegionChooser::on_draw(const Cai Line 403  bool DimRegionChooser::on_draw(const Cai
403    
404                          // draw fill for zone                          // draw fill for zone
405                          bool isSelectedZone = this->dimzones[dimension].count(j);                          bool isSelectedZone = this->dimzones[dimension].count(j);
406                          Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);                          bool isMainSelection =
407                                this->maindimcase.find(dimension) != this->maindimcase.end() &&
408                                this->maindimcase[dimension] == j;
409                            if (isMainSelection)
410                                Gdk::Cairo::set_source_rgba(cr, blue);
411                            else if (isSelectedZone)
412                                cr->set_source(blueHatchedSurfacePattern);
413                            else
414                                Gdk::Cairo::set_source_rgba(cr, white);
415    
416                          cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);                          cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
417                          cr->fill();                          cr->fill();
418    
# Line 420  bool DimRegionChooser::on_draw(const Cai Line 470  bool DimRegionChooser::on_draw(const Cai
470                          if (j != 0) {                          if (j != 0) {
471                              // draw fill for zone                              // draw fill for zone
472                              bool isSelectedZone = this->dimzones[dimension].count(j-1);                              bool isSelectedZone = this->dimzones[dimension].count(j-1);
473                              Gdk::Cairo::set_source_rgba(cr, isSelectedZone ? red : white);                              bool isMainSelection =
474                                    this->maindimcase.find(dimension) != this->maindimcase.end() &&
475                                    this->maindimcase[dimension] == (j-1);
476                                if (isMainSelection)
477                                    Gdk::Cairo::set_source_rgba(cr, blue);
478                                else if (isSelectedZone)
479                                    cr->set_source(blueHatchedSurfacePattern);
480                                else
481                                    Gdk::Cairo::set_source_rgba(cr, white);
482                              cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);                              cr->rectangle(prevX + 1, y + 1, x - prevX - 1, h - 1);
483                              cr->fill();                              cr->fill();
484    
# Line 1137  void DimRegionChooser::delete_dimension_ Line 1195  void DimRegionChooser::delete_dimension_
1195      refresh_all();      refresh_all();
1196  }  }
1197    
1198    // Cmd key on Mac, Ctrl key on all other OSs
1199    static const guint primaryKeyL =
1200        #if defined(__APPLE__)
1201        GDK_KEY_Meta_L;
1202        #else
1203        GDK_KEY_Control_L;
1204        #endif
1205    
1206    static const guint primaryKeyR =
1207        #if defined(__APPLE__)
1208        GDK_KEY_Meta_R;
1209        #else
1210        GDK_KEY_Control_R;
1211        #endif
1212    
1213  bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {  bool DimRegionChooser::onKeyPressed(GdkEventKey* key) {
1214      //printf("key down\n");      //printf("key down 0x%x\n", key->keyval);
1215      if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)      if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1216          multiSelectKeyDown = true;          multiSelectKeyDown = true;
1217        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
1218            primaryKeyDown = true;
1219        if (key->keyval == GDK_KEY_Shift_L || key->keyval == GDK_KEY_Shift_R)
1220            shiftKeyDown = true;
1221    
1222        //FIXME: hmm, for some reason GDKMM does not fire arrow key down events, so we are doing those handlers in the key up handler instead for now
1223        /*if (key->keyval == GDK_KEY_Left)
1224            select_prev_dimzone();
1225        if (key->keyval == GDK_KEY_Right)
1226            select_next_dimzone();
1227        if (key->keyval == GDK_KEY_Up)
1228            select_prev_dimension();
1229        if (key->keyval == GDK_KEY_Down)
1230            select_next_dimension();*/
1231      return false;      return false;
1232  }  }
1233    
1234  bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {  bool DimRegionChooser::onKeyReleased(GdkEventKey* key) {
1235      //printf("key up\n");      //printf("key up 0x%x\n", key->keyval);
1236      if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)      if (key->keyval == GDK_KEY_Control_L || key->keyval == GDK_KEY_Control_R)
1237          multiSelectKeyDown = false;          multiSelectKeyDown = false;
1238        if (key->keyval == primaryKeyL || key->keyval == primaryKeyR)
1239            primaryKeyDown = false;
1240        if (key->keyval == GDK_KEY_Shift_L || key->keyval == GDK_KEY_Shift_R)
1241            shiftKeyDown = false;
1242    
1243        if (!has_focus()) return false;
1244    
1245        // avoid conflict with Ctrl+Left and Ctrl+Right accelerators on mainwindow
1246        // (which is supposed to switch between regions)
1247        if (primaryKeyDown) return false;
1248    
1249        // avoid conflict with Alt+Shift+Left and Alt+Shift+Right accelerators on
1250        // mainwindow
1251        if (shiftKeyDown) return false;
1252    
1253        if (key->keyval == GDK_KEY_Left)
1254            select_prev_dimzone();
1255        if (key->keyval == GDK_KEY_Right)
1256            select_next_dimzone();
1257        if (key->keyval == GDK_KEY_Up)
1258            select_prev_dimension();
1259        if (key->keyval == GDK_KEY_Down)
1260            select_next_dimension();
1261    
1262      return false;      return false;
1263  }  }
1264    
# Line 1168  void DimRegionChooser::resetSelectedZone Line 1279  void DimRegionChooser::resetSelectedZone
1279      gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];      gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];
1280    
1281      bool isValidZone;      bool isValidZone;
1282      this->maindimcase = caseOfDimRegion(dimrgn, &isValidZone);      this->maindimcase = dimensionCaseOf(dimrgn);
     if (!isValidZone) {  
         queue_draw(); // redraw required parts  
         return;  
     }  
1283    
1284      for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();      for (std::map<gig::dimension_t,int>::const_iterator it = this->maindimcase.begin();
1285           it != this->maindimcase.end(); ++it)           it != this->maindimcase.end(); ++it)
# Line 1203  bool DimRegionChooser::select_dimregion( Line 1310  bool DimRegionChooser::select_dimregion(
1310      return false; //.selection failed      return false; //.selection failed
1311  }  }
1312    
1313    void DimRegionChooser::select_next_dimzone(bool add) {
1314        select_dimzone_by_dir(+1, add);
1315    }
1316    
1317    void DimRegionChooser::select_prev_dimzone(bool add) {
1318        select_dimzone_by_dir(-1, add);
1319    }
1320    
1321    void DimRegionChooser::select_dimzone_by_dir(int dir, bool add) {
1322        if (!region) return;
1323        if (!region->Dimensions) return;
1324        if (focus_line < 0) focus_line = 0;
1325        if (focus_line >= region->Dimensions) focus_line = region->Dimensions - 1;
1326    
1327        maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1328        if (maindimtype == gig::dimension_none) {
1329            printf("maindimtype -> none\n");
1330            return;
1331        }
1332    
1333        if (maindimcase.empty()) {
1334            maindimcase = dimensionCaseOf(region->pDimensionRegions[maindimregno]);
1335            if (maindimcase.empty()) {
1336                printf("caseOfDimregion(%d) -> empty\n", maindimregno);
1337                return;
1338            }
1339        }
1340    
1341        int z = (dir > 0) ? maindimcase[maindimtype] + 1 : maindimcase[maindimtype] - 1;
1342        if (z < 0) z = 0;
1343        if (z >= region->pDimensionDefinitions[focus_line].zones)
1344            z = region->pDimensionDefinitions[focus_line].zones - 1;
1345    
1346        maindimcase[maindimtype] = z;
1347    
1348        ::gig::DimensionRegion* dr = dimensionRegionMatching(maindimcase, region);
1349        if (!dr) {
1350            printf("select_dimzone_by_dir(%d) -> !dr\n", dir);
1351            return;
1352        }
1353    
1354        maindimregno = getDimensionRegionIndex(dr);
1355    
1356        if (!add) {
1357            // reset selected dimregion zones
1358            dimzones.clear();
1359        }
1360        for (DimensionCase::const_iterator it = maindimcase.begin();
1361             it != maindimcase.end(); ++it)
1362        {
1363            dimzones[it->first].insert(it->second);
1364        }
1365    
1366        dimregion_selected();
1367    
1368        // disabled: would overwrite dimregno with wrong value
1369        //refresh_all();
1370        // so requesting just a raw repaint instead:
1371        queue_draw();
1372    }
1373    
1374    void DimRegionChooser::select_next_dimension() {
1375        if (!region) return;
1376        focus_line++;
1377        if (focus_line >= region->Dimensions)
1378            focus_line = region->Dimensions - 1;
1379        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1380        queue_draw();
1381    }
1382    
1383    void DimRegionChooser::select_prev_dimension() {
1384        if (!region) return;
1385        focus_line--;
1386        if (focus_line < 0)
1387            focus_line = 0;
1388        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1389        queue_draw();
1390    }
1391    
1392  gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {  gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {
1393      if (!region) return NULL;      if (!region) return NULL;
1394      return region->pDimensionRegions[maindimregno];      return region->pDimensionRegions[maindimregno];

Legend:
Removed from v.3105  
changed lines
  Added in v.3134

  ViewVC Help
Powered by ViewVC