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