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