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