/[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 3131 by schoenebeck, Thu Apr 27 17:28:01 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 "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        if (key->keyval == GDK_KEY_Left)
1250            select_prev_dimzone();
1251        if (key->keyval == GDK_KEY_Right)
1252            select_next_dimzone();
1253        if (key->keyval == GDK_KEY_Up)
1254            select_prev_dimension();
1255        if (key->keyval == GDK_KEY_Down)
1256            select_next_dimension();
1257    
1258      return false;      return false;
1259  }  }
1260    
# Line 1168  void DimRegionChooser::resetSelectedZone Line 1275  void DimRegionChooser::resetSelectedZone
1275      gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];      gig::DimensionRegion* dimrgn = region->pDimensionRegions[maindimregno];
1276    
1277      bool isValidZone;      bool isValidZone;
1278      this->maindimcase = caseOfDimRegion(dimrgn, &isValidZone);      this->maindimcase = dimensionCaseOf(dimrgn);
     if (!isValidZone) {  
         queue_draw(); // redraw required parts  
         return;  
     }  
1279    
1280      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();
1281           it != this->maindimcase.end(); ++it)           it != this->maindimcase.end(); ++it)
# Line 1203  bool DimRegionChooser::select_dimregion( Line 1306  bool DimRegionChooser::select_dimregion(
1306      return false; //.selection failed      return false; //.selection failed
1307  }  }
1308    
1309    void DimRegionChooser::select_next_dimzone() {
1310        select_dimzone_by_dir(+1);
1311    }
1312    
1313    void DimRegionChooser::select_prev_dimzone() {
1314        select_dimzone_by_dir(-1);
1315    }
1316    
1317    void DimRegionChooser::select_dimzone_by_dir(int dir) {
1318        if (!region) return;
1319        if (!region->Dimensions) return;
1320        if (focus_line < 0) focus_line = 0;
1321        if (focus_line >= region->Dimensions) focus_line = region->Dimensions - 1;
1322    
1323        maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1324        if (maindimtype == gig::dimension_none) {
1325            printf("maindimtype -> none\n");
1326            return;
1327        }
1328    
1329        if (maindimcase.empty()) {
1330            maindimcase = dimensionCaseOf(region->pDimensionRegions[maindimregno]);
1331            if (maindimcase.empty()) {
1332                printf("caseOfDimregion(%d) -> empty\n", maindimregno);
1333                return;
1334            }
1335        }
1336    
1337        int z = (dir > 0) ? maindimcase[maindimtype] + 1 : maindimcase[maindimtype] - 1;
1338        if (z < 0) z = 0;
1339        if (z >= region->pDimensionDefinitions[focus_line].zones)
1340            z = region->pDimensionDefinitions[focus_line].zones - 1;
1341    
1342        maindimcase[maindimtype] = z;
1343    
1344        ::gig::DimensionRegion* dr = dimensionRegionMatching(maindimcase, region);
1345        if (!dr) {
1346            printf("select_dimzone_by_dir(%d) -> !dr\n", dir);
1347            return;
1348        }
1349    
1350        maindimregno = getDimensionRegionIndex(dr);
1351    
1352        // reset selected dimregion zones
1353        dimzones.clear();
1354        for (DimensionCase::const_iterator it = maindimcase.begin();
1355             it != maindimcase.end(); ++it)
1356        {
1357            dimzones[it->first].insert(it->second);
1358        }
1359    
1360        dimregion_selected();
1361    
1362        // disabled: would overwrite dimregno with wrong value
1363        //refresh_all();
1364        // so requesting just a raw repaint instead:
1365        queue_draw();
1366    }
1367    
1368    void DimRegionChooser::select_next_dimension() {
1369        if (!region) return;
1370        focus_line++;
1371        if (focus_line >= region->Dimensions)
1372            focus_line = region->Dimensions - 1;
1373        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1374        queue_draw();
1375    }
1376    
1377    void DimRegionChooser::select_prev_dimension() {
1378        if (!region) return;
1379        focus_line--;
1380        if (focus_line < 0)
1381            focus_line = 0;
1382        this->maindimtype = region->pDimensionDefinitions[focus_line].dimension;
1383        queue_draw();
1384    }
1385    
1386  gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {  gig::DimensionRegion* DimRegionChooser::get_main_dimregion() const {
1387      if (!region) return NULL;      if (!region) return NULL;
1388      return region->pDimensionRegions[maindimregno];      return region->pDimensionRegions[maindimregno];

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

  ViewVC Help
Powered by ViewVC