USGS

Isis 3.0 Object Programmers' Reference

Home

RubberBandComboBox.cpp

00001 #include "RubberBandComboBox.h"
00002 
00003 #include <QAction>
00004 
00005 #include "Tool.h"
00006 
00007 namespace Isis {
00016   RubberBandComboBox::RubberBandComboBox(unsigned int bandingOptions, unsigned int defaultOption, bool showIndicatorColors) :
00017     QComboBox() {
00018 
00019     p_showIndicatorColors = showIndicatorColors;
00020     setDuplicatesEnabled(false);
00021     setEditable(false);
00022     setIconSize(QSize(24, 24));
00023 
00024     // We must call setCurrentIndex with the default, or the banding mode won't be set properly. Thus,
00025     //   we do need a default even if they pass in zero, which means default.
00026     defaultOption = getDefault(defaultOption, bandingOptions);
00027 
00028     QAction *escapeKeyHit = new QAction(this);
00029     escapeKeyHit->setShortcut(Qt::Key_Escape);
00030     connect(escapeKeyHit, SIGNAL(activated()), RubberBandTool::getInstance(), SLOT(escapeKeyPress()));
00031     addAction(escapeKeyHit);
00032 
00033     // The tool tip and what's this need to be set. The tool tip won't change, but the what's this should detail how to use the
00034     //   tools. So, set the tool tip and start the what's this. The what's this should only have the available tools, so create it as
00035     //   we add the tools.
00036     setToolTip("Select Measurement Type");
00037     QString whatsThis =
00038       "<b>Function:</b> This drop down will enable you to switch between drawing various shapes.";
00039 
00040     p_bandingOptionStrings.push_back("Circle");
00041     if((bandingOptions & Circle) == Circle) {
00042       QIcon circleIcon(toolIconDir() + "/qview_circle.png");
00043       circleIcon.addFile(toolIconDir() + "/qview_circle_active.png", QSize(24, 24), QIcon::Active);
00044 
00045       addItem(circleIcon, p_bandingOptionStrings[p_bandingOptionStrings.size()-1], QVariant((int)Circle));
00046 
00047       whatsThis += "<br><br>When <b>Circle</b> is selected, you can draw a perfect circle. To draw a circle, \
00048                      click at a corner of the circle, drag the mouse until the circle is the correct shape, and release the mouse \
00049                      to complete the circle.";
00050 
00051       if((defaultOption & Circle) == Circle) {
00052         setCurrentIndex(findText(p_bandingOptionStrings[ p_bandingOptionStrings.size()-1 ]));
00053       }
00054     }
00055 
00056     p_bandingOptionStrings.push_back("Ellipse");
00057     if((bandingOptions & Ellipse) == Ellipse) {
00058       QIcon ellipseIcon(toolIconDir() + "/qview_ellipse.png");
00059       ellipseIcon.addFile(toolIconDir() + "/qview_ellipse_active.png", QSize(24, 24), QIcon::Active);
00060 
00061       addItem(ellipseIcon, p_bandingOptionStrings[p_bandingOptionStrings.size()-1], QVariant((int)Ellipse));
00062 
00063       whatsThis += "<br><br>When <b>Ellipse</b> is selected, you can draw an ellipse. To draw an ellipse, \
00064                      click at a corner of the ellipse, drag the mouse until the ellipse is the correct shape, and release the mouse \
00065                      to complete the ellipse.";
00066 
00067       if((defaultOption & Ellipse) == Ellipse) {
00068         setCurrentIndex(findText(p_bandingOptionStrings[ p_bandingOptionStrings.size()-1 ]));
00069       }
00070     }
00071 
00072     p_bandingOptionStrings.push_back("Rectangle");
00073     if((bandingOptions & Rectangle) == Rectangle) {
00074       QIcon rectangleIcon(toolIconDir() + "/qview_rectangle.png");
00075       rectangleIcon.addFile(toolIconDir() + "/qview_rectangle_active.png", QSize(24, 24), QIcon::Active);
00076 
00077       addItem(rectangleIcon, p_bandingOptionStrings[p_bandingOptionStrings.size()-1], QVariant((int)Rectangle));
00078 
00079       whatsThis += "<br><br>When <b>Rectangle</b> is selected, you can draw a rectangle. To draw a rectangle, \
00080                      click a corner of the rectangle, drag the mouse until the rectangle is the correct size and shape, and release the mouse \
00081                      to complete the rectangle.";
00082 
00083       if((defaultOption & Rectangle) == Rectangle) {
00084         setCurrentIndex(findText(p_bandingOptionStrings[ p_bandingOptionStrings.size()-1 ]));
00085       }
00086     }
00087 
00088     p_bandingOptionStrings.push_back("Rotated Rectangle");
00089     if((bandingOptions & RotatedRectangle) == RotatedRectangle) {
00090       QIcon rotatedRectangleIcon(toolIconDir() + "/qview_rotated_rectangle.png");
00091 
00092       addItem(rotatedRectangleIcon, p_bandingOptionStrings[p_bandingOptionStrings.size()-1], QVariant((int)RotatedRectangle));
00093 
00094       whatsThis += "<br><br>When <b>Rotated Rectangle</b> is selected, you can draw a rectangle rotated about its center. To draw a rotated rectangle, \
00095                      click, drag the mouse to form the first side of the rectangle and determine it's rotation, and release the mouse. \
00096                      Now, the final side of the rotated rectangle should follow the mouse. \
00097                      Click again when the rotated rectangle is the correct size to complete the rotated rectangle.";
00098 
00099       if(p_showIndicatorColors) {
00100         whatsThis += " The data will be calculated starting from the initial (GREEN) side of the rotated rectangle and ending at the opposite \
00101                       side of the rotated rectangle.";
00102       }
00103 
00104       if((defaultOption & RotatedRectangle) == RotatedRectangle) {
00105         setCurrentIndex(findText(p_bandingOptionStrings[ p_bandingOptionStrings.size()-1 ]));
00106       }
00107     }
00108 
00109     p_bandingOptionStrings.push_back("Polygon");
00110     if((bandingOptions & Polygon) == Polygon) {
00111       QIcon polygonIcon(toolIconDir() + "/qview_polygon.png");
00112 
00113       addItem(polygonIcon, p_bandingOptionStrings[p_bandingOptionStrings.size()-1], QVariant((int)Polygon));
00114 
00115       whatsThis += "<br><br>When <b>Polygon</b> is selected, you can draw any closed polygon. To begin drawing a polygon, \
00116                      click where you want the start point. Now, click for any new vertices or click and drag the mouse to form irregular shapes. \
00117                      When completed, double click the final vertex and the figure will close.";
00118 
00119       if((defaultOption & Polygon) == Polygon) {
00120         setCurrentIndex(findText(p_bandingOptionStrings[ p_bandingOptionStrings.size()-1 ]));
00121       }
00122     }
00123 
00124     p_bandingOptionStrings.push_back("Line");
00125     if((bandingOptions & Line) == Line) {
00126       QIcon lineIcon(toolIconDir() + "/qview_line.png");
00127       lineIcon.addFile(toolIconDir() + "/qview_line_active.png", QSize(24, 24), QIcon::Active);
00128 
00129       addItem(lineIcon, p_bandingOptionStrings[p_bandingOptionStrings.size()-1], QVariant((int)Line));
00130 
00131       whatsThis += "<br><br>When <b>Line</b> is selected, you can draw a line. "
00132           "To draw a line, click the starting point of the line, drag the "
00133           "mouse until the line is the correct length in the correct direction,"
00134           " and release the mouse.  To draw vertical or horizontal lines, press"
00135           " and hold the control key while drawing your line";
00136 
00137       if((defaultOption & Line) == Line) {
00138         setCurrentIndex(findText(p_bandingOptionStrings[ p_bandingOptionStrings.size()-1 ]));
00139       }
00140     }
00141 
00142     p_bandingOptionStrings.push_back("Segmented Line");
00143     if((bandingOptions & SegmentedLine) == SegmentedLine) {
00144       QIcon segmentedLineIcon(toolIconDir() + "/qview_segmentedline.png");
00145 
00146       addItem(segmentedLineIcon, p_bandingOptionStrings[p_bandingOptionStrings.size()-1], QVariant((int)SegmentedLine));
00147 
00148       whatsThis += "<br><br>When <b>Segmented Line</b> is selected, you can draw any open polygon. To begin drawing a segmented line, \
00149                      click where you want the start point. Now, click for any new vertices or click and drag the mouse to form irregular shapes. \
00150                      When completed, double click the final vertex.";
00151 
00152       if((defaultOption & SegmentedLine) == SegmentedLine) {
00153         setCurrentIndex(findText(p_bandingOptionStrings[ p_bandingOptionStrings.size()-1 ]));
00154       }
00155     }
00156 
00157     p_bandingOptionStrings.push_back("Angle");
00158     if((bandingOptions & Angle) == Angle) {
00159       QIcon angleIcon;
00160       angleIcon.addFile(toolIconDir() + "/qview_angle.png", QSize(24, 24), QIcon::Normal);
00161       //angleIcon.addFile(toolIconDir()+"/qview_angle_active.png", QSize(24,24), QIcon::Active);
00162 
00163       addItem(angleIcon, p_bandingOptionStrings[p_bandingOptionStrings.size()-1], QVariant((int)Angle));
00164 
00165       whatsThis += "<br><br>When <b>Angle</b> is selected, you can draw an angle from zero to 180 degrees. To draw an angle, \
00166                      click where the first corner should go, then click where the vertex should go. Finally, click where the final \
00167                      side of the angle should end to complete the angle.";
00168 
00169       if((defaultOption & Angle) == Angle) {
00170         setCurrentIndex(findText(p_bandingOptionStrings[ p_bandingOptionStrings.size()-1 ]));
00171       }
00172     }
00173 
00174     connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(selectionChanged(int)));
00175     connect(this, SIGNAL(activated(int)), this, SLOT(selectionChanged(int)));
00176 
00177     setWhatsThis(whatsThis);
00178   }
00179 
00180 
00188   void RubberBandComboBox::selectionChanged(int index) {
00189     switch(itemData(index).toInt()) {
00190       case Angle:
00191         showAngle();
00192         break;
00193       case Circle:
00194         showCircle();
00195         break;
00196       case Ellipse:
00197         showEllipse();
00198         break;
00199       case Line:
00200         showLine();
00201         break;
00202       case Rectangle:
00203         showRectangle();
00204         break;
00205       case RotatedRectangle:
00206         showRotatedRectangle();
00207         break;
00208       case Polygon:
00209         showPolygon();
00210         break;
00211       case SegmentedLine:
00212         showSegmentedLine();
00213         break;
00214       default:
00215         // This shouldn't happen
00216         RubberBandTool::disable();
00217         break;
00218     }
00219   }
00220 
00225   void RubberBandComboBox::reset() {
00226     selectionChanged(currentIndex());
00227   }
00228 
00229 
00239   unsigned int RubberBandComboBox::getDefault(unsigned int defaultOption, unsigned int bandingOptions) {
00240     // The default will always be to set
00241     //   the default selection to the first, and thus the least significant bit in bandingOptions.
00242     //   We're going to find the least significant bit by shifting left and right the same amount of times,
00243     //   causing the bits to be truncated, until we see the result isn't the same as the beginning which means
00244     //   a bit was truncated. When we see this, we know where the least significant bit is so shift a '1' left by
00245     //  the appropriate amount.
00246     if(defaultOption == 0) {
00247       defaultOption = bandingOptions;
00248     }
00249 
00250     // Find the least significant bit, that's our default.
00251     int power = 0;
00252 
00253     // While cuting off the next significant bit does nothing, keep going.
00254     while(((defaultOption >> (power + 1)) << (power + 1)) == defaultOption) {
00255       power ++;
00256     }
00257 
00258     defaultOption = 1 << power;
00259 
00260     // We are done figuring out the default option.
00261     return defaultOption;
00262   }
00263 }