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