1 //------------------------------------------------------------------------------ 2 // Copyright (c) 2001-2002, OpenBeOS 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a 5 // copy of this software and associated documentation files (the "Software"), 6 // to deal in the Software without restriction, including without limitation 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 // and/or sell copies of the Software, and to permit persons to whom the 9 // Software is furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 // DEALINGS IN THE SOFTWARE. 21 // 22 // File Name: TextControl.cpp 23 // Author: Frans van Nispen (xlr8@tref.nl) 24 // Description: BTextControl displays text that can act like a control. 25 //------------------------------------------------------------------------------ 26 27 // Standard Includes ----------------------------------------------------------- 28 #include <stdio.h> 29 30 // System Includes ------------------------------------------------------------- 31 #include <TextControl.h> 32 #include <Window.h> 33 #include <Message.h> 34 35 // Project Includes ------------------------------------------------------------ 36 37 // Local Includes -------------------------------------------------------------- 38 #include "TextInput.h" 39 40 // Local Defines --------------------------------------------------------------- 41 42 // Globals --------------------------------------------------------------------- 43 44 //------------------------------------------------------------------------------ 45 BTextControl::BTextControl(BRect frame, const char* name, const char* label, 46 const char* text, BMessage* message, uint32 mask, 47 uint32 flags) 48 : BControl(frame, name, label, message, mask, flags) 49 { 50 if (label) 51 { 52 fDivider = frame.Width() / 2.0f; 53 } 54 else 55 { 56 // no label 57 fDivider = 0.0f; 58 } 59 60 fModificationMessage = NULL; 61 62 frame = Bounds(); 63 if (fDivider) 64 { 65 frame.left = fDivider + 5.0f; 66 } 67 68 BRect rect(frame); 69 rect.OffsetTo(0,0); 70 71 frame.OffsetBy(-2,1); 72 73 rect.InsetBy(2,2); 74 fText = new _BTextInput_(this, frame, "text", rect); 75 fText->SetText(text); 76 AddChild(fText); 77 } 78 //------------------------------------------------------------------------------ 79 BTextControl::~BTextControl() 80 { 81 if (fText) 82 { 83 fText->RemoveSelf(); 84 delete fText; 85 } 86 } 87 //------------------------------------------------------------------------------ 88 BTextControl::BTextControl(BMessage* data) 89 : BControl(data) 90 { 91 if (data->FindInt32("_a_label", (int32*)&fLabelAlign) != B_OK) 92 { 93 fLabelAlign = B_ALIGN_LEFT; 94 } 95 96 alignment textAlign; 97 if (data->FindInt32("_a_text", (int32*)&textAlign) != B_OK) 98 { 99 fText->SetAlignment(B_ALIGN_LEFT); 100 } 101 else 102 { 103 fText->SetAlignment(textAlign); 104 } 105 106 if (data->FindFloat("_divide", &fDivider) != B_OK) 107 { 108 if (Label()) 109 fDivider = Frame().Width()/2.0f; 110 else 111 fDivider = 0.0f; 112 } 113 114 if (data->FindMessage("_mod_msg", fModificationMessage) != B_OK) 115 { 116 fModificationMessage = NULL; // Is this really necessary? 117 } 118 119 // TODO: Recover additional info as per final implementation of Archive() 120 } 121 //------------------------------------------------------------------------------ 122 BArchivable* BTextControl::Instantiate(BMessage* data) 123 { 124 if (!validate_instantiation(data,"BTextControl")) 125 { 126 return NULL; 127 } 128 129 return new BTextControl(data); 130 } 131 //------------------------------------------------------------------------------ 132 status_t BTextControl::Archive(BMessage* data, bool deep = true) const 133 { 134 // TODO: compare against original version and finish 135 status_t err = BView::Archive(data, deep); 136 137 if (!err) 138 err = data->AddInt32("_a_label", fLabelAlign); 139 if (!err) 140 err = data->AddInt32("_a_text", fText->Alignment()); 141 if (!err) 142 err = data->AddFloat("_divide", fDivider); 143 if (!err && fModificationMessage) 144 err = data->AddMessage("_mod_msg", fModificationMessage); 145 146 return err; 147 } 148 //------------------------------------------------------------------------------ 149 void BTextControl::SetText(const char* text) 150 { 151 fText->SetText(text); 152 } 153 //------------------------------------------------------------------------------ 154 const char* BTextControl::Text() const 155 { 156 return fText->Text(); 157 } 158 //------------------------------------------------------------------------------ 159 void BTextControl::SetValue(int32 value) 160 { 161 } 162 //------------------------------------------------------------------------------ 163 status_t BTextControl::Invoke(BMessage* msg = NULL) 164 { 165 return BControl::Invoke(msg); 166 } 167 //------------------------------------------------------------------------------ 168 BTextView* BTextControl::TextView() const 169 { 170 return (BTextView*)fText; 171 } 172 //------------------------------------------------------------------------------ 173 void BTextControl::SetModificationMessage(BMessage* message) 174 { 175 fModificationMessage = message; 176 } 177 //------------------------------------------------------------------------------ 178 BMessage* BTextControl::ModificationMessage() const 179 { 180 return fModificationMessage; 181 } 182 //------------------------------------------------------------------------------ 183 void BTextControl::SetAlignment(alignment label, alignment text) 184 { 185 fLabelAlign = label; 186 fText->SetAlignment(text); 187 } 188 //------------------------------------------------------------------------------ 189 void BTextControl::GetAlignment(alignment* label, alignment* text) const 190 { 191 *label = fLabelAlign; 192 *text = fText->Alignment(); 193 } 194 //------------------------------------------------------------------------------ 195 void BTextControl::SetDivider(float dividing_line) 196 { 197 fDivider = dividing_line; 198 // here I need some code to resize and invalidate the textView 199 200 BRect frame = fText->Frame(); 201 if (fDivider) 202 { 203 frame.left = fDivider + 5.0f; 204 } 205 else 206 { 207 frame.left = 0.0f; 208 } 209 210 if (!frame.IsValid()) 211 { 212 frame.left = frame.right - 6.0f; 213 } 214 215 fText->ResizeTo( frame.Width(), frame.Height()); 216 // fText->FrameResized( frame.Width(), frame.Height()); 217 fText->MoveTo( frame.left, frame.top); 218 fText->Invalidate(); 219 220 Invalidate(); 221 } 222 //------------------------------------------------------------------------------ 223 float BTextControl::Divider() const 224 { 225 return fDivider; 226 } 227 //------------------------------------------------------------------------------ 228 void BTextControl::Draw(BRect rect) 229 { 230 SetLowColor(ViewColor()); 231 BFont font; 232 GetFont(&font); 233 font_height fh; 234 font.GetHeight(&fh); 235 236 if (Label()) 237 { 238 float y = ceil(fh.ascent + fh.descent + fh.leading) + 2.0f; 239 float x; 240 switch (fLabelAlign) 241 { 242 case B_ALIGN_RIGHT: 243 x = fDivider - font.StringWidth(Label()) - 3.0f; 244 break; 245 246 case B_ALIGN_CENTER: 247 x = fDivider - font.StringWidth(Label())/2.0f; 248 break; 249 250 default: 251 x = 3.0f; 252 break; 253 } 254 255 SetHighColor(tint_color(ui_color(B_PANEL_BACKGROUND_COLOR), 256 IsEnabled() ? B_DARKEN_MAX_TINT : B_DISABLED_LABEL_TINT)); 257 DrawString(Label(), BPoint(x, y)); 258 } 259 260 rect = fText->Frame(); 261 262 rgb_color base = ui_color(B_PANEL_BACKGROUND_COLOR); 263 264 rect.InsetBy(-1,-1); 265 SetHighColor(tint_color(base, IsEnabled() ? 266 B_DARKEN_1_TINT : B_DARKEN_2_TINT)); 267 StrokeLine(BPoint(rect.left,rect.bottom), BPoint(rect.left, rect.top)); 268 StrokeLine(BPoint(rect.left+1.0f,rect.top), BPoint(rect.right, rect.top)); 269 SetHighColor(tint_color(base, IsEnabled() ? 270 B_LIGHTEN_MAX_TINT : B_LIGHTEN_2_TINT)); 271 StrokeLine(BPoint(rect.left+1.0f,rect.bottom), 272 BPoint(rect.right, rect.bottom)); 273 StrokeLine(BPoint(rect.right,rect.bottom), 274 BPoint(rect.right, rect.top+1.0f)); 275 } 276 //------------------------------------------------------------------------------ 277 void BTextControl::MouseDown(BPoint where) 278 { 279 if (IsEnabled()) 280 { 281 MakeFocus(true); 282 } 283 } 284 void BTextControl::AttachedToWindow() 285 { 286 BControl::AttachedToWindow(); 287 if (Parent()) 288 { 289 SetViewColor(Parent()->ViewColor()); 290 } 291 292 float w; 293 float h; 294 GetPreferredSize(&w, &h); 295 ResizeTo(Bounds().Width(), h); 296 fText->ResizeTo(fText->Bounds().Width(), h); 297 } 298 void BTextControl::MakeFocus(bool state = true) 299 { 300 if (IsEnabled()) 301 { 302 fText->MakeFocus(state); 303 Invalidate(); 304 } 305 } 306 //------------------------------------------------------------------------------ 307 void BTextControl::SetEnabled(bool state) 308 { 309 fText->SetEnabled(state); 310 BControl::SetEnabled(state); 311 } 312 //------------------------------------------------------------------------------ 313 void BTextControl::GetPreferredSize(float* width, float* height) 314 { 315 BFont font; 316 GetFont(&font); 317 font_height fh; 318 font.GetHeight(&fh); 319 320 *height = ceil(fh.ascent + fh.descent + fh.leading) + 7.0f; 321 322 // TODO: this one I need to find out 323 *width = 4.0f + ceil(font.StringWidth(Label()))*2.0f; 324 } 325 //------------------------------------------------------------------------------ 326 void BTextControl::ResizeToPreferred() 327 { 328 float w; 329 float h; 330 GetPreferredSize(&w, &h); 331 BView::ResizeTo(w,h); 332 } 333 //------------------------------------------------------------------------------ 334 void BTextControl::SetFlags(uint32 flags) 335 { 336 BView::SetFlags(flags); 337 } 338 //------------------------------------------------------------------------------ 339 void BTextControl::MessageReceived(BMessage* msg) 340 { 341 switch(msg->what) 342 { 343 case B_CONTROL_MODIFIED: 344 if (fModificationMessage) 345 { 346 BControl::Invoke(fModificationMessage); 347 } 348 break; 349 350 default: 351 BControl::MessageReceived(msg); 352 break; 353 } 354 } 355 //------------------------------------------------------------------------------ 356 BHandler* BTextControl::ResolveSpecifier(BMessage* msg, int32 index, 357 BMessage* specifier, int32 form, 358 const char* property) 359 { 360 return NULL; 361 } 362 //------------------------------------------------------------------------------ 363 status_t BTextControl::GetSupportedSuites(BMessage* data) 364 { 365 return B_OK; 366 } 367 //------------------------------------------------------------------------------ 368 void BTextControl::MouseUp(BPoint pt) 369 { 370 BControl::MouseUp(pt); 371 } 372 //------------------------------------------------------------------------------ 373 void BTextControl::MouseMoved(BPoint pt, uint32 code, const BMessage* msg) 374 { 375 BControl::MouseMoved(pt, code, msg); 376 } 377 //------------------------------------------------------------------------------ 378 void BTextControl::DetachedFromWindow() 379 { 380 BControl::DetachedFromWindow(); 381 } 382 //------------------------------------------------------------------------------ 383 void BTextControl::AllAttached() 384 { 385 BControl::AllAttached(); 386 } 387 //------------------------------------------------------------------------------ 388 void BTextControl::AllDetached() 389 { 390 BControl::AllDetached(); 391 } 392 //------------------------------------------------------------------------------ 393 void BTextControl::FrameMoved(BPoint newPosition) 394 { 395 BControl::FrameMoved(newPosition); 396 } 397 //------------------------------------------------------------------------------ 398 void BTextControl::FrameResized(float newWidth, float newHeight) 399 { 400 BControl::FrameResized(newWidth, newHeight); 401 } 402 //------------------------------------------------------------------------------ 403 void BTextControl::WindowActivated(bool active) 404 { 405 BControl::WindowActivated(active); 406 } 407 //------------------------------------------------------------------------------ 408 status_t BTextControl::Perform(perform_code d, void* arg) 409 { 410 return BControl::Perform(d, arg); 411 } 412 //------------------------------------------------------------------------------ 413 void BTextControl::_ReservedTextControl1() 414 { 415 } 416 //------------------------------------------------------------------------------ 417 void BTextControl::_ReservedTextControl2() 418 { 419 } 420 //------------------------------------------------------------------------------ 421 void BTextControl::_ReservedTextControl3() 422 { 423 } 424 //------------------------------------------------------------------------------ 425 void BTextControl::_ReservedTextControl4() 426 { 427 } 428 //------------------------------------------------------------------------------ 429 BTextControl& BTextControl::operator=(const BTextControl&) 430 { 431 // Assignment not allowed 432 return *this; 433 } 434 //------------------------------------------------------------------------------ 435 436 /* 437 * $Log $ 438 * 439 * $Id $ 440 * 441 */ 442 443