1 // ValControl.h 2 // +++++ cortex integration 23aug99: 3 // - way too many protected members 4 // - config'able font 5 // - implement GetPreferredSize() (should work before the view is attached 6 // to a window -- doable?) 7 // - keyboard entry (pop-up text field) 8 // - 'spin' mode: value changes based on vertical distance of pointer 9 // (configurable; set buttons/modifiers to activate either mode?) 10 // 11 // - should parameter binding happen at this level? 12 // +++++ how about a ValControlFactory? give it a BParameter, get back a 13 // ValControl subclass... +++++ 14 // 15 // e.moon 16jan99 16 // 17 // ABSTRACT CLASS: ValControl 18 // An abstract base class for 'value controls' -- interface 19 // components that display a value that may be modified via 20 // click-drag. Other editing methods (such as 'click, then 21 // type') may be supported by subclasses. 22 // 23 // IMPLEMENT 24 // getValue() and setValue(), for raw (BParameter-style) value access 25 // MessageReceived(), to handle: 26 // M_SET_VALUE 27 // M_GET_VALUE 28 // M_OFFSET_VALUE (May be sent by segments during mouse action, 29 // +++++ is a faster method needed?) 30 // 31 // NOTES 32 // The control view consists of: 33 // 34 // - One or more segments. Each segment is individually 35 // draggable. Subclasses may mix segment types, or add 36 // and remove segments dynamically. 37 // 38 // - A manipulator region, to which subcontrols (such as 'spin 39 // arrows') may be added. 40 // 41 // Views/segments may be aligned flush left or flush right. The 42 // side towards which views are aligned may be referred to as 43 // the 'anchor' side. 44 // 45 // Quickie interface guidelines: 46 // 47 // - Value controls are always underlined, indicating that the 48 // value is editable. (+++++ possible extension: dotted-underline 49 // for continuous variation, and solid for discrete/step variation) 50 // 51 // - When a value control's 'click action' is to pop down a menu of 52 // available choices (or pop up any sort of non-typable display) 53 // this should be indicated by a small right triangle in the 54 // manipulator area. 55 // +++++ this may need some clarification; pop-down sliders, for example? 56 // 57 // * HISTORY 58 // e.moon 19sep99 Cleanup 59 // e.moon 23aug99 begun Cortex integration 60 // e.moon 17jan99 started 61 62 #ifndef __ValControl_H__ 63 #define __ValControl_H__ 64 65 #include <vector> 66 67 #include <Bitmap.h> 68 #include <View.h> 69 #include <Font.h> 70 #include <Control.h> 71 #include <Message.h> 72 73 #include "ValCtrlLayoutEntry.h" 74 75 #include "cortex_defs.h" 76 __BEGIN_CORTEX_NAMESPACE 77 78 class ValControlSegment; 79 80 // ---------------------------------------------------------------- // 81 82 83 /* abstract */ 84 class ValControl : public BControl { 85 typedef BControl _inherited; 86 87 public: // types & constants 88 // child-view alignment options: 89 enum align_mode { 90 ALIGN_FLUSH_LEFT, 91 ALIGN_FLUSH_RIGHT 92 }; 93 94 // alignment flags +++++ 23aug99: not implemented -- should they be? 95 enum align_flags { 96 ALIGN_NONE = 0, 97 ALIGN_GROW = 1 98 }; 99 100 // should value update messages be sent asynchronously (during 101 // a mouse operation) or synchronously (after the mouse is 102 // released)? 103 enum update_mode { 104 UPDATE_ASYNC, 105 UPDATE_SYNC 106 }; 107 108 enum entry_location { 109 LEFT_MOST = 0, 110 FROM_LEFT = 0, 111 RIGHT_MOST = 1, 112 FROM_RIGHT = 1 113 }; 114 115 // layout system state +++++ 116 117 public: // types 118 119 public: // messages (all ValControl-related messages go here!) 120 enum message_t { 121 122 // Set value of a control or segment: 123 // [your value field(s)] or "_value" (string) 124 M_SET_VALUE = ValControl_message_base, 125 126 // Request for value of control/segment: 127 // [your value field(s)] 128 M_GET_VALUE, 129 130 // ... reply to M_GET_VALUE with this: 131 // [your value field(s)] 132 M_VALUE 133 }; 134 135 public: // hooks 136 137 // * parameter-mode value access 138 139 // called to set the control's value from raw BParameter data 140 virtual void setValue( 141 const void* data, 142 size_t size)=0; 143 144 // called to request the control's value in raw form 145 virtual void getValue( 146 void* data, 147 size_t* ioSize)=0; 148 149 // * string value access 150 151 virtual status_t setValueFrom( 152 const char* text)=0; 153 154 virtual status_t getString( 155 BString& buffer)=0; 156 157 // called when a child view's preferred size has changed; 158 // it's up to the ValControl to grant the resize request. 159 // Return true to notify the child that the request has 160 // been granted, or false if denied (the default.) 161 162 virtual bool childResizeRequest( 163 BView* child) { return false; } 164 165 public: // ctor/dtor/accessors 166 virtual ~ValControl(); 167 168 // value-access methods are left up to the subclasses, 169 // since they'll take varying types of arguments. 170 // (M_SET_VALUE and M_GET_VALUE should always behave 171 // as you'd expect, with a 'value' field of the appropriate 172 // type replacing or returning the current value.) +++++ decrepit 173 // 174 // Note that all implementations offering pop-up keyboard entry 175 // must accept an M_SET_VALUE with a value of B_STRING_TYPE. 176 177 // get/set update mode (determines whether value updates are 178 // sent to the target during mouse operations, or only on 179 // mouse-up) 180 update_mode updateMode() const; 181 void setUpdateMode( 182 update_mode mode); 183 184 // +++++ get/set font used by segments 185 // (would separate 'value' and 'label' fonts be a good move?) 186 // const BFont* font() const; 187 188 const BFont* labelFont() const; //nyi 189 void setLabelFont( 190 const BFont* labelFont); //nyi 191 192 const BFont* valueFont() const; //nyi 193 void setValueFont( 194 const BFont* valueFont); //nyi 195 196 // get baseline y offset: this is measured relative to the top of the 197 // view 198 float baselineOffset() const; 199 200 // segment padding: this amount of padding is added to the 201 // right of each segment bounds-rectangle 202 float segmentPadding() const; 203 204 // fast drag rate: returns ratio of pixels:units for fast 205 // (left-button) dragging 206 float fastDragRate() const; //nyi 207 208 // slow drag rate: returns ratio for precise (both/middle-button) 209 // dragging 210 float slowDragRate() const; //nyi 211 212 // fetch back-buffer 213 BView* backBufferView() const; //nyi 214 BBitmap* backBuffer() const; //nyi 215 216 // pop up keyboard input field 217 // +++++ should this turn into a message? 218 virtual void showEditField(); 219 220 public: // debugging [23aug99] 221 virtual void dump(); 222 223 public: // BControl impl. 224 // SetValue(), Value() aren't defined, since they only support 225 // 32-bit integer values. TextControl provides a precedent for 226 // this kind of naughtiness. 227 228 // empty implementation (hands off to BControl) 229 virtual void SetEnabled( 230 bool enabled); 231 232 public: // BView impl. 233 234 // handle initial layout stuff: 235 virtual void AttachedToWindow(); 236 virtual void AllAttached(); 237 238 // paint decorations (& decimal point) 239 virtual void Draw( 240 BRect updateRect); 241 242 virtual void drawDecimalPoint( 243 ValCtrlLayoutEntry& entry); 244 245 // handle frame resize (grow backbuffer if need be) 246 virtual void FrameResized( 247 float width, 248 float height); 249 250 // calculate minimum size 251 virtual void GetPreferredSize( 252 float* outWidth, 253 float* outHeight); 254 255 virtual void MakeFocus( 256 bool focused=true); 257 258 virtual void MouseDown( 259 BPoint where); 260 261 public: // BHandler impl. 262 virtual void MessageReceived( 263 BMessage* message); 264 265 public: // archiving/instantiation 266 ValControl( 267 BMessage* archive); 268 269 status_t Archive( 270 BMessage* archive, 271 bool deep=true) const; 272 273 protected: // internal ctor/operations 274 ValControl( 275 BRect frame, 276 const char* name, 277 const char* label, 278 BMessage* message, 279 align_mode alignMode, 280 align_flags alignFlags, 281 update_mode updateMode=UPDATE_ASYNC, 282 bool backBuffer=true); 283 284 // add segment view (which is responsible for generating its 285 // own ValCtrlLayoutEntry) 286 void add( 287 ValControlSegment* segment, 288 entry_location from, 289 uint16 distance=0); 290 291 // add general view (manipulator, label, etc.) 292 // (the entry's frame rectangle will be filled in) 293 // covers ValCtrlLayoutEntry ctor: 294 void add( 295 ValCtrlLayoutEntry& entry, 296 entry_location from); 297 298 // access child-view ValCtrlLayoutEntry 299 // (indexOf returns index from left) 300 const ValCtrlLayoutEntry& entryAt( 301 uint16 offset) const; 302 303 const ValCtrlLayoutEntry& entryAt( 304 entry_location from, 305 uint16 distance=0) const; 306 307 uint16 indexOf( 308 BView* child) const; 309 310 uint16 countEntries() const; 311 312 private: // steaming entrails 313 314 // (re-)initialize the backbuffer 315 void _allocBackBuffer( 316 float width, 317 float height); 318 319 // insert a layout entry in ordered position (doesn't call 320 // AddChild()) 321 void _insertEntry( 322 ValCtrlLayoutEntry& entry, 323 uint16 index); 324 325 // move given entry horizontally (update child view's position 326 // and size as well, if any) 327 void _slideEntry( 328 int index, 329 float delta); 330 331 // turn entry_location/offset into an index: 332 uint16 _locationToIndex( 333 entry_location from, 334 uint16 distance=0) const; 335 336 void _getDefaultEntrySize( 337 ValCtrlLayoutEntry::entry_type type, 338 float* outWidth, 339 float* outHeight); 340 341 void _invalidateAll(); 342 343 protected: // impl. members 344 345 // the set of visible segments and other child views, 346 // in left-to-right. top-to-bottom order 347 typedef vector<ValCtrlLayoutEntry> layout_set; 348 layout_set m_layoutSet; 349 350 // true if value has been changed since last request 351 // (allows caching of value) 352 bool m_dirty; 353 354 // when should messages be sent to the target? 355 update_mode m_updateMode; 356 357 // layout stuff 358 // BFont m_font; 359 360 BFont m_labelFont; 361 BFont m_valueFont; 362 363 align_mode m_alignMode; 364 align_flags m_alignFlags; 365 366 // the bounds rectangle requested upon construction. 367 // if the ALIGN_GROW flag is set, the real bounds 368 // rectangle may be wider 369 BRect m_origBounds; 370 371 // backbuffer (made available to segments for flicker-free 372 // drawing) 373 bool m_haveBackBuffer; 374 BBitmap* m_backBuffer; 375 BView* m_backBufferView; 376 377 static const float s_segmentPadding; 378 379 static const float s_decimalPointWidth; 380 static const float s_decimalPointHeight; 381 382 private: // guts 383 class fnInitChild; 384 }; 385 386 __END_CORTEX_NAMESPACE 387 #endif /* __ValControl_H__ */ 388