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 #ifndef VAL_CONTROL_H 62 #define VAL_CONTROL_H 63 64 65 #include "cortex_defs.h" 66 67 #include "ValCtrlLayoutEntry.h" 68 69 #include <Bitmap.h> 70 #include <Control.h> 71 #include <Font.h> 72 #include <Message.h> 73 #include <View.h> 74 75 #include <vector> 76 77 __BEGIN_CORTEX_NAMESPACE 78 79 class ValControlSegment; 80 81 82 /* abstract */ 83 class ValControl : public BControl { 84 public: 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(const void* data, size_t size) = 0; 141 142 // called to request the control's value in raw form 143 virtual void getValue(void* data, size_t* ioSize) = 0; 144 145 // * string value access 146 147 virtual status_t setValueFrom(const char* text) = 0; 148 149 virtual status_t getString(BString& buffer) = 0; 150 151 // called when a child view's preferred size has changed; 152 // it's up to the ValControl to grant the resize request. 153 // Return true to notify the child that the request has 154 // been granted, or false if denied (the default.) 155 156 virtual bool childResizeRequest(BView* child) { return false; } 157 158 public: // ctor/dtor/accessors 159 virtual ~ValControl(); 160 161 // value-access methods are left up to the subclasses, 162 // since they'll take varying types of arguments. 163 // (M_SET_VALUE and M_GET_VALUE should always behave 164 // as you'd expect, with a 'value' field of the appropriate 165 // type replacing or returning the current value.) +++++ decrepit 166 // 167 // Note that all implementations offering pop-up keyboard entry 168 // must accept an M_SET_VALUE with a value of B_STRING_TYPE. 169 170 // get/set update mode (determines whether value updates are 171 // sent to the target during mouse operations, or only on 172 // mouse-up) 173 update_mode updateMode() const; 174 void setUpdateMode(update_mode mode); 175 176 // +++++ get/set font used by segments 177 // (would separate 'value' and 'label' fonts be a good move?) 178 // const BFont* font() const; 179 180 const BFont* labelFont() const; //nyi 181 void setLabelFont(const BFont* labelFont); //nyi 182 183 const BFont* valueFont() const; //nyi 184 void setValueFont(const BFont* valueFont); //nyi 185 186 // get baseline y offset: this is measured relative to the top of the 187 // view 188 float baselineOffset() const; 189 190 // segment padding: this amount of padding is added to the 191 // right of each segment bounds-rectangle 192 float segmentPadding() const; 193 194 // fast drag rate: returns ratio of pixels:units for fast 195 // (left-button) dragging 196 float fastDragRate() const; //nyi 197 198 // slow drag rate: returns ratio for precise (both/middle-button) 199 // dragging 200 float slowDragRate() const; //nyi 201 202 // fetch back-buffer 203 BView* backBufferView() const; //nyi 204 BBitmap* backBuffer() const; //nyi 205 206 // pop up keyboard input field 207 // +++++ should this turn into a message? 208 virtual void showEditField(); 209 210 public: // debugging [23aug99] 211 virtual void dump(); 212 213 public: // BControl impl. 214 // SetValue(), Value() aren't defined, since they only support 215 // 32-bit integer values. TextControl provides a precedent for 216 // this kind of naughtiness. 217 218 // empty implementation (hands off to BControl) 219 virtual void SetEnabled(bool enabled); 220 221 public: // BView impl. 222 223 // handle initial layout stuff: 224 virtual void AttachedToWindow(); 225 virtual void AllAttached(); 226 227 // paint decorations (& decimal point) 228 virtual void Draw(BRect updateRect); 229 230 virtual void drawDecimalPoint(ValCtrlLayoutEntry& entry); 231 232 // handle frame resize (grow backbuffer if need be) 233 virtual void FrameResized(float width, float height); 234 235 // calculate minimum size 236 virtual void GetPreferredSize(float* outWidth, float* outHeight); 237 238 virtual void MakeFocus(bool focused = true); 239 240 virtual void MouseDown(BPoint where); 241 242 public: 243 virtual void MessageReceived(BMessage* message); 244 245 public: // archiving/instantiation 246 ValControl(BMessage* archive); 247 248 status_t Archive(BMessage* archive, bool deep = true) const; 249 250 protected: // internal ctor/operations 251 ValControl(BRect frame, const char* name, const char* label, 252 BMessage* message, align_mode alignMode, align_flags alignFlags, 253 update_mode updateMode = UPDATE_ASYNC, bool backBuffer = true); 254 255 // Add segment view (which is responsible for generating its 256 // own ValCtrlLayoutEntry) 257 void _Add(ValControlSegment* segment, entry_location from, 258 uint16 distance = 0); 259 260 // Add general view (manipulator, label, etc.) 261 // (the entry's frame rectangle will be filled in) 262 // covers ValCtrlLayoutEntry ctor: 263 void _Add(ValCtrlLayoutEntry& entry, entry_location from); 264 265 // access child-view ValCtrlLayoutEntry 266 // (_IndexOf returns index from left) 267 const ValCtrlLayoutEntry& _EntryAt(uint16 offset) const; 268 269 const ValCtrlLayoutEntry& _EntryAt(entry_location from, 270 uint16 distance = 0) const; 271 272 uint16 _IndexOf(BView* child) const; 273 274 uint16 CountEntries() const; 275 276 private: // steaming entrails 277 // (re-)initialize the backbuffer 278 void _AllocBackBuffer(float width, float height); 279 280 // insert a layout entry in ordered position (doesn't call 281 // AddChild()) 282 void _InsertEntry(ValCtrlLayoutEntry& entry, uint16 index); 283 284 // move given entry horizontally (update child view's position 285 // and size as well, if any) 286 void _SlideEntry(int index, float delta); 287 288 // turn entry_location/offset into an index: 289 uint16 _LocationToIndex(entry_location from, uint16 distance = 0) const; 290 291 void _GetDefaultEntrySize(ValCtrlLayoutEntry::entry_type type, 292 float* outWidth, float* outHeight); 293 294 void _InvalidateAll(); 295 296 private: 297 // the set of visible segments and other child views, 298 // in left-to-right. top-to-bottom order 299 typedef std::vector<ValCtrlLayoutEntry> layout_set; 300 layout_set fLayoutSet; 301 302 // true if value has been changed since last request 303 // (allows caching of value) 304 bool fDirty; 305 306 // when should messages be sent to the target? 307 update_mode fUpdateMode; 308 309 BFont fLabelFont; 310 BFont fValueFont; 311 312 align_mode fAlignMode; 313 align_flags fAlignFlags; 314 315 // the bounds rectangle requested upon construction. 316 // if the ALIGN_GROW flag is set, the real bounds 317 // rectangle may be wider 318 BRect fOrigBounds; 319 320 // backbuffer (made available to segments for flicker-free 321 // drawing) 322 bool fHaveBackBuffer; 323 BBitmap* fBackBuffer; 324 BView* fBackBufferView; 325 326 static const float fSegmentPadding; 327 328 static const float fDecimalPointWidth; 329 static const float fDecimalPointHeight; 330 331 private: 332 class fnInitChild; 333 }; 334 335 __END_CORTEX_NAMESPACE 336 #endif // VAL_CONTROL_H 337