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
110class ValControlSegment;
111
112
113/* abstract */
114class 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
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