/** Copyright (c) 1999-2000, Eric Moon.* All rights reserved.** Redistribution and use in source and binary forms, with or without* modification, are permitted provided that the following conditions* are met:** 1. Redistributions of source code must retain the above copyright* notice, this list of conditions, and the following disclaimer.** 2. Redistributions in binary form must reproduce the above copyright* notice, this list of conditions, and the following disclaimer in the* documentation and/or other materials provided with the distribution.** 3. The name of the author may not be used to endorse or promote products* derived from this software without specific prior written permission.** THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES* OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS FOR A PARTICULAR* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.*/// ValControl.h// +++++ cortex integration 23aug99:// - way too many protected members// - config'able font// - implement GetPreferredSize() (should work before the view is attached// to a window -- doable?)// - keyboard entry (pop-up text field)// - 'spin' mode: value changes based on vertical distance of pointer// (configurable; set buttons/modifiers to activate either mode?)//// - should parameter binding happen at this level?// +++++ how about a ValControlFactory? give it a BParameter, get back a// ValControl subclass... +++++//// e.moon 16jan99//// ABSTRACT CLASS: ValControl// An abstract base class for 'value controls' -- interface// components that display a value that may be modified via// click-drag. Other editing methods (such as 'click, then// type') may be supported by subclasses.//// IMPLEMENT// getValue() and setValue(), for raw (BParameter-style) value access// MessageReceived(), to handle:// M_SET_VALUE// M_GET_VALUE// M_OFFSET_VALUE (May be sent by segments during mouse action,// +++++ is a faster method needed?)//// NOTES// The control view consists of://// - One or more segments. Each segment is individually// draggable. Subclasses may mix segment types, or Add// and remove segments dynamically.//// - A manipulator region, to which subcontrols (such as 'spin// arrows') may be added.//// Views/segments may be aligned flush left or flush right. The// side towards which views are aligned may be referred to as// the 'anchor' side.//// Quickie interface guidelines://// - Value controls are always underlined, indicating that the// value is editable. (+++++ possible extension: dotted-underline// for continuous variation, and solid for discrete/step variation)//// - When a value control's 'click action' is to pop down a menu of// available choices (or pop up any sort of non-typable display)// this should be indicated by a small right triangle in the// manipulator area.// +++++ this may need some clarification; pop-down sliders, for example?//// * HISTORY// e.moon 19sep99 Cleanup// e.moon 23aug99 begun Cortex integration// e.moon 17jan99 started#ifndef VAL_CONTROL_H#define VAL_CONTROL_H#include "cortex_defs.h"#include "ValCtrlLayoutEntry.h"#include <Bitmap.h>#include <Control.h>#include <Font.h>#include <Message.h>#include <View.h>#include <vector>__BEGIN_CORTEX_NAMESPACEclass ValControlSegment;/* abstract */class ValControl : public BControl {public:typedef BControl _Inherited;public: // types & constants// child-view alignment options:enum align_mode {ALIGN_FLUSH_LEFT,ALIGN_FLUSH_RIGHT};// alignment flags +++++ 23aug99: not implemented -- should they be?enum align_flags {ALIGN_NONE = 0,ALIGN_GROW = 1};// should value update messages be sent asynchronously (during// a mouse operation) or synchronously (after the mouse is// released)?enum update_mode {UPDATE_ASYNC,UPDATE_SYNC};enum entry_location {LEFT_MOST = 0,FROM_LEFT = 0,RIGHT_MOST = 1,FROM_RIGHT = 1};// layout system state +++++public: // typespublic: // messages (all ValControl-related messages go here!)enum message_t {// Set value of a control or segment:// [your value field(s)] or "_value" (string)M_SET_VALUE = ValControl_message_base,// Request for value of control/segment:// [your value field(s)]M_GET_VALUE,// ... reply to M_GET_VALUE with this:// [your value field(s)]M_VALUE};public: // hooks// * parameter-mode value access// called to set the control's value from raw BParameter datavirtual void setValue(const void* data, size_t size) = 0;// called to request the control's value in raw formvirtual void getValue(void* data, size_t* ioSize) = 0;// * string value accessvirtual status_t setValueFrom(const char* text) = 0;virtual status_t getString(BString& buffer) = 0;// called when a child view's preferred size has changed;// it's up to the ValControl to grant the resize request.// Return true to notify the child that the request has// been granted, or false if denied (the default.)virtual bool childResizeRequest(BView* child) { return false; }public: // ctor/dtor/accessorsvirtual ~ValControl();// value-access methods are left up to the subclasses,// since they'll take varying types of arguments.// (M_SET_VALUE and M_GET_VALUE should always behave// as you'd expect, with a 'value' field of the appropriate// type replacing or returning the current value.) +++++ decrepit//// Note that all implementations offering pop-up keyboard entry// must accept an M_SET_VALUE with a value of B_STRING_TYPE.// get/set update mode (determines whether value updates are// sent to the target during mouse operations, or only on// mouse-up)update_mode updateMode() const;void setUpdateMode(update_mode mode);// +++++ get/set font used by segments// (would separate 'value' and 'label' fonts be a good move?)// const BFont* font() const;const BFont* labelFont() const; //nyivoid setLabelFont(const BFont* labelFont); //nyiconst BFont* valueFont() const; //nyivoid setValueFont(const BFont* valueFont); //nyi// get baseline y offset: this is measured relative to the top of the// viewfloat baselineOffset() const;// segment padding: this amount of padding is added to the// right of each segment bounds-rectanglefloat segmentPadding() const;// fast drag rate: returns ratio of pixels:units for fast// (left-button) draggingfloat fastDragRate() const; //nyi// slow drag rate: returns ratio for precise (both/middle-button)// draggingfloat slowDragRate() const; //nyi// fetch back-bufferBView* backBufferView() const; //nyiBBitmap* backBuffer() const; //nyi// pop up keyboard input field// +++++ should this turn into a message?virtual void showEditField();public: // debugging [23aug99]virtual void dump();public: // BControl impl.// SetValue(), Value() aren't defined, since they only support// 32-bit integer values. TextControl provides a precedent for// this kind of naughtiness.// empty implementation (hands off to BControl)virtual void SetEnabled(bool enabled);public: // BView impl.// handle initial layout stuff:virtual void AttachedToWindow();virtual void AllAttached();// paint decorations (& decimal point)virtual void Draw(BRect updateRect);virtual void drawDecimalPoint(ValCtrlLayoutEntry& entry);// handle frame resize (grow backbuffer if need be)virtual void FrameResized(float width, float height);// calculate minimum sizevirtual void GetPreferredSize(float* outWidth, float* outHeight);virtual void MakeFocus(bool focused = true);virtual void MouseDown(BPoint where);public:virtual void MessageReceived(BMessage* message);public: // archiving/instantiationValControl(BMessage* archive);status_t Archive(BMessage* archive, bool deep = true) const;protected: // internal ctor/operationsValControl(BRect frame, const char* name, const char* label,BMessage* message, align_mode alignMode, align_flags alignFlags,update_mode updateMode = UPDATE_ASYNC, bool backBuffer = true);// Add segment view (which is responsible for generating its// own ValCtrlLayoutEntry)void _Add(ValControlSegment* segment, entry_location from,uint16 distance = 0);// Add general view (manipulator, label, etc.)// (the entry's frame rectangle will be filled in)// covers ValCtrlLayoutEntry ctor:void _Add(ValCtrlLayoutEntry& entry, entry_location from);// access child-view ValCtrlLayoutEntry// (_IndexOf returns index from left)const ValCtrlLayoutEntry& _EntryAt(uint16 offset) const;const ValCtrlLayoutEntry& _EntryAt(entry_location from,uint16 distance = 0) const;uint16 _IndexOf(BView* child) const;uint16 CountEntries() const;private: // steaming entrails// (re-)initialize the backbuffervoid _AllocBackBuffer(float width, float height);// insert a layout entry in ordered position (doesn't call// AddChild())void _InsertEntry(ValCtrlLayoutEntry& entry, uint16 index);// move given entry horizontally (update child view's position// and size as well, if any)void _SlideEntry(int index, float delta);// turn entry_location/offset into an index:uint16 _LocationToIndex(entry_location from, uint16 distance = 0) const;void _GetDefaultEntrySize(ValCtrlLayoutEntry::entry_type type,float* outWidth, float* outHeight);void _InvalidateAll();private:// the set of visible segments and other child views,// in left-to-right. top-to-bottom ordertypedef std::vector<ValCtrlLayoutEntry> layout_set;layout_set fLayoutSet;// true if value has been changed since last request// (allows caching of value)bool fDirty;// when should messages be sent to the target?update_mode fUpdateMode;BFont fLabelFont;BFont fValueFont;align_mode fAlignMode;align_flags fAlignFlags;// the bounds rectangle requested upon construction.// if the ALIGN_GROW flag is set, the real bounds// rectangle may be widerBRect fOrigBounds;// backbuffer (made available to segments for flicker-free// drawing)bool fHaveBackBuffer;BBitmap* fBackBuffer;BView* fBackBufferView;static const float fSegmentPadding;static const float fDecimalPointWidth;static const float fDecimalPointHeight;private:class fnInitChild;};__END_CORTEX_NAMESPACE#endif // VAL_CONTROL_H