|
Isis 3.0 Object Programmers' Reference |
Home |
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 }