1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 36 #include "DialogPane.h" 37 38 #include <ControlLook.h> 39 #include <LayoutUtils.h> 40 41 #include "Thread.h" 42 #include "Utilities.h" 43 #include "Window.h" 44 45 46 const rgb_color kNormalColor = {150, 150, 150, 255}; 47 const rgb_color kHighlightColor = {100, 100, 0, 255}; 48 49 50 // #pragma mark - PaneSwitch 51 52 53 PaneSwitch::PaneSwitch(BRect frame, const char* name, bool leftAligned, 54 uint32 resizeMask, uint32 flags) 55 : 56 BControl(frame, name, "", 0, resizeMask, flags), 57 fLeftAligned(leftAligned), 58 fPressing(false), 59 fLabelOn(NULL), 60 fLabelOff(NULL) 61 { 62 } 63 64 65 PaneSwitch::PaneSwitch(const char* name, bool leftAligned, uint32 flags) 66 : 67 BControl(name, "", 0, flags), 68 fLeftAligned(leftAligned), 69 fPressing(false), 70 fLabelOn(NULL), 71 fLabelOff(NULL) 72 { 73 } 74 75 76 PaneSwitch::~PaneSwitch() 77 { 78 free(fLabelOn); 79 free(fLabelOff); 80 } 81 82 83 void 84 PaneSwitch::Draw(BRect) 85 { 86 BRect bounds(Bounds()); 87 88 // Draw the label, if any 89 const char* label = fLabelOff; 90 if (fLabelOn != NULL && Value() == B_CONTROL_ON) 91 label = fLabelOn; 92 93 if (label != NULL) { 94 BPoint point; 95 float latchSize = be_plain_font->Size(); 96 float labelDist = latchSize + ceilf(latchSize / 2.0); 97 if (fLeftAligned) 98 point.x = labelDist; 99 else 100 point.x = bounds.right - labelDist - StringWidth(label); 101 102 SetHighUIColor(B_PANEL_TEXT_COLOR); 103 font_height fontHeight; 104 GetFontHeight(&fontHeight); 105 point.y = (bounds.top + bounds.bottom 106 - ceilf(fontHeight.ascent) - ceilf(fontHeight.descent)) / 2 107 + ceilf(fontHeight.ascent); 108 109 DrawString(label, point); 110 } 111 112 // draw the latch 113 if (fPressing) 114 DrawInState(kPressed); 115 else if (Value()) 116 DrawInState(kExpanded); 117 else 118 DrawInState(kCollapsed); 119 120 // ...and the focus indication 121 if (!IsFocus() || !Window()->IsActive()) 122 return; 123 124 rgb_color markColor = ui_color(B_KEYBOARD_NAVIGATION_COLOR); 125 126 BeginLineArray(2); 127 AddLine(BPoint(bounds.left + 2, bounds.bottom - 1), 128 BPoint(bounds.right - 2, bounds.bottom - 1), markColor); 129 AddLine(BPoint(bounds.left + 2, bounds.bottom), 130 BPoint(bounds.right - 2, bounds.bottom), kWhite); 131 EndLineArray(); 132 } 133 134 135 void 136 PaneSwitch::MouseDown(BPoint) 137 { 138 if (!IsEnabled()) 139 return; 140 141 fPressing = true; 142 MouseDownThread<PaneSwitch>::TrackMouse(this, &PaneSwitch::DoneTracking, 143 &PaneSwitch::Track); 144 Invalidate(); 145 } 146 147 148 void 149 PaneSwitch::GetPreferredSize(float* _width, float* _height) 150 { 151 BSize size = MinSize(); 152 if (_width != NULL) 153 *_width = size.width; 154 155 if (_height != NULL) 156 *_height = size.height; 157 } 158 159 160 BSize 161 PaneSwitch::MinSize() 162 { 163 BSize size; 164 float onLabelWidth = StringWidth(fLabelOn); 165 float offLabelWidth = StringWidth(fLabelOff); 166 float labelWidth = max_c(onLabelWidth, offLabelWidth); 167 float latchSize = be_plain_font->Size(); 168 size.width = latchSize; 169 if (labelWidth > 0.0) 170 size.width += ceilf(latchSize / 2.0) + labelWidth; 171 172 font_height fontHeight; 173 GetFontHeight(&fontHeight); 174 size.height = ceilf(fontHeight.ascent) + ceilf(fontHeight.descent); 175 size.height = max_c(size.height, latchSize); 176 177 return BLayoutUtils::ComposeSize(ExplicitMinSize(), size); 178 } 179 180 181 BSize 182 PaneSwitch::MaxSize() 183 { 184 return BLayoutUtils::ComposeSize(ExplicitMaxSize(), MinSize()); 185 } 186 187 188 BSize 189 PaneSwitch::PreferredSize() 190 { 191 return BLayoutUtils::ComposeSize(ExplicitPreferredSize(), MinSize()); 192 } 193 194 195 void 196 PaneSwitch::SetLabels(const char* labelOn, const char* labelOff) 197 { 198 free(fLabelOn); 199 free(fLabelOff); 200 201 if (labelOn != NULL) 202 fLabelOn = strdup(labelOn); 203 else 204 fLabelOn = NULL; 205 206 if (labelOff != NULL) 207 fLabelOff = strdup(labelOff); 208 else 209 fLabelOff = NULL; 210 211 Invalidate(); 212 InvalidateLayout(); 213 } 214 215 216 void 217 PaneSwitch::DoneTracking(BPoint point) 218 { 219 BRect bounds(Bounds()); 220 bounds.InsetBy(-3, -3); 221 222 fPressing = false; 223 Invalidate(); 224 if (bounds.Contains(point)) { 225 SetValue(!Value()); 226 Invoke(); 227 } 228 } 229 230 231 void 232 PaneSwitch::Track(BPoint point, uint32) 233 { 234 BRect bounds(Bounds()); 235 bounds.InsetBy(-3, -3); 236 237 bool newPressing = bounds.Contains(point); 238 if (newPressing != fPressing) { 239 fPressing = newPressing; 240 Invalidate(); 241 } 242 } 243 244 245 void 246 PaneSwitch::DrawInState(PaneSwitch::State state) 247 { 248 BRect rect(0, 0, be_plain_font->Size(), be_plain_font->Size()); 249 rect.OffsetBy(1, 1); 250 251 rgb_color arrowColor = state == kPressed ? kHighlightColor : kNormalColor; 252 int32 arrowDirection = BControlLook::B_RIGHT_ARROW; 253 float tint = IsEnabled() && Window()->IsActive() ? B_DARKEN_3_TINT 254 : B_DARKEN_1_TINT; 255 256 switch (state) { 257 case kCollapsed: 258 arrowDirection = BControlLook::B_RIGHT_ARROW; 259 break; 260 261 case kPressed: 262 arrowDirection = BControlLook::B_RIGHT_DOWN_ARROW; 263 break; 264 265 case kExpanded: 266 arrowDirection = BControlLook::B_DOWN_ARROW; 267 break; 268 } 269 270 SetDrawingMode(B_OP_COPY); 271 be_control_look->DrawArrowShape(this, rect, rect, arrowColor, 272 arrowDirection, 0, tint); 273 } 274