xref: /haiku/src/apps/cortex/ValControl/ValControl.h (revision 93a78ecaa45114d68952d08c4778f073515102f2)
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