00001 /* 00002 * PROPRIETARY INFORMATION. This software is proprietary to 00003 * Side Effects Software Inc., and is not to be reproduced, 00004 * transmitted, or disclosed in any way without written permission. 00005 * 00006 * Produced by: 00007 * Cristin Barghiel 00008 * Side Effects Software Inc. 00009 * 20 Maud St. 00010 * Toronto, Ontario, M5V 2M5 00011 * Canada 00012 * 416-366-4607 00013 * 00014 * NAME: Direct manipulation library (C++) 00015 * 00016 * COMMENTS: 00017 * The base class of a BM state. 00018 * 00019 */ 00020 #ifndef __BM_State_H__ 00021 #define __BM_State_H__ 00022 00023 #include "BM_API.h" 00024 #include <UI/UI_Keyboard.h> 00025 #include "BM_ParmState.h" 00026 00027 class UT_Undo; 00028 class PI_StateTemplate; 00029 class OP_Node; 00030 class OP_Network; 00031 class BM_OpHandleLink; 00032 00033 class BM_API BM_StateFlags 00034 { 00035 public: 00036 BM_StateFlags() { 00037 sticky = 1; // must be sticky by default (obsolete) 00038 entered = 0; 00039 scratch = 0; 00040 preempted = 0; 00041 busybuild = 0; 00042 wantlocate = 0; 00043 modifier = 0; 00044 concealed = 0; 00045 } 00046 unsigned sticky:1, // does not pop back after an operation 00047 entered:3, // the way it was entered (BM_EntryType) 00048 scratch:3, // entered from scratch 00049 preempted:1, // have I been interrupted or not 00050 busybuild:1, // I'm in the building stage (not editing) 00051 wantlocate:1, // want to get locate events 00052 modifier:1, // changes geometry, etc or not? 00053 concealed:1; // are we concealed in a non-visible desktop? 00054 }; 00055 00056 class BM_API BM_State : public BM_ParmState 00057 { 00058 public: 00059 enum BM_GenerateMode { BM_INLINE = 0x01, 00060 BM_OUTLINE = 0x02, 00061 BM_REGENERATE = 0x04 00062 }; 00063 00064 // Class constructor and destructor. 00065 BM_State( BM_SceneManager &app, 00066 PI_StateTemplate &templ, 00067 const char *cursor = 0, 00068 const char *const *vnames = 0, 00069 UI_EventMethod const *vmethods = 0); 00070 virtual ~BM_State(void); 00071 00072 // Return the current status string for this state. This is used by the 00073 // viewport rendering code to display some extra information in the 00074 // viewport instead of in the blue status bar. If this string is 00075 // returned empty (the default), it is ignored. 00076 virtual void status(UT_String &s) const { s.harden(""); } 00077 00078 // Render whatever extra things may be needed beside the status string. 00079 // You can assume that translations to that location have been performed 00080 // already (i.e., you can render without moving). 00081 virtual void renderStatusExtras(RE_Render *) {} 00082 00083 virtual int isHandle() const { return 0; } 00084 00085 // Enter or exit this state. There are 2 entry types: 00086 // 1. fulltime (BM_FULLTIME_ENTRY): the state stays on until another one 00087 // is invoked; that other state replaces the current. 00088 // 2. overlay (BM_OVERLAY_ENTRY): also known as "volatile", it gets 00089 // triggered by pressing a key and stays on until the key is released. 00090 // Upon exiting it returns control to the previous state. It is not 00091 // allowed to overlay the current state with itself or to have 00092 // nested overlay states. When starting the overlay state, the 00093 // previous state is _interrupted_, not exited; then, it is _resumed_. 00094 // enter() returns 0 if entered and -1 if not. 00095 virtual int enter(BM_SimpleState::BM_EntryType how); 00096 virtual void exit (void); 00097 00098 00099 // 00100 // When the current desktop is changed, it's possible that the state might 00101 // have to clean up some stuff. The concealed() method is called when the 00102 // desktop is changed, the revealed() method when the desktop is re-opened. 00103 // Note, it may be possible to get a revealed() called without having the 00104 // concealed called. 00105 // 00106 virtual void concealState(); 00107 virtual void revealState(); 00108 00109 // Interrupt this state or resume its activity. These methods should 00110 // be called by overlay states when entering and exiting respectively. 00111 // Interrupt will leave the state in limbo and will usually turn off 00112 // the feed from the app; resume will do the opposite. interrupt() 00113 // should not change the modeler's current state. If 'state' is given, it 00114 // is the state that has interrupted/resumed us. This may be particularly 00115 // useful if we are interrupted by a handle (possibly ours). 00116 virtual void interrupt(BM_SimpleState *state = 0); 00117 virtual void resume (BM_SimpleState *state = 0); 00118 00119 // Pre-process a mouse start event, in case we wish to push/position a 00120 // handle so the mouse event is processed by the handle. 00121 virtual int preprocessSelect(UI_Event *event); 00122 00123 // Deal with the events the modeler has sent me. Scene events imply use 00124 // of the mouse. Return 1 if consumed and 0 otherwise. 00125 virtual int handleMouseEvent (UI_Event *event); 00126 virtual int handleMouseWheelEvent(UI_Event *event); 00127 00128 // Return false if un-handled. 00129 virtual bool handleDoubleClickEvent(UI_Event *); 00130 00131 virtual int handleArrowEvent (UI_Event *event); 00132 00133 // Called whenever the geometry changed (but not when the change was 00134 // caused by modelling in this state) 00135 virtual void handleGeoChangedEvent(UI_Event *); 00136 00137 // Called by the viewport to allow the state to render its own bits. 00138 // It calls doRender(), which is what derived classes should implement. 00139 virtual void render(RE_Render *r, short x, short y); 00140 00141 // The state might contain something that it wants to display in a 00142 // non-destructive manner (eg. by xor'ing). Note that this method is not 00143 // called during the normal rendering of the workbench. 00144 virtual void renderPartialOverlay(RE_Render *r, short x, short y); 00145 00146 // Similar to enter, but totally from scratch. At this level, it's the 00147 // same as doing an enter. It cannot be entered in volatile mode. 00148 // We can start generating either in inline (insert) mode 00149 // or in branching-off mode. The generation mode is relevant only when 00150 // generating ops in a network. 00151 virtual int generate(BM_SimpleState::BM_EntryType how, 00152 bool insertmode = true); 00153 00154 // Start or stop the generation process. At this level, generating doesn't 00155 // mean a thing. We can start generating either in inline (insert) mode 00156 // or in branching-off mode. The inline mode is the default. The mode 00157 // is relevant only when generating ops in a network. 00158 void startGenerating(BM_State::BM_GenerateMode how = 00159 BM_State::BM_INLINE) 00160 { myFlags.scratch = how; } 00161 virtual void stopGenerating (void) { myFlags.scratch = 0; } 00162 00163 // Restart cancels what is currently being done and starts generating anew. 00164 virtual void restart(void); 00165 00166 // Add or remove interests to events that trigger you as an overlay. 00167 // Once the interests have been removed, you can no longer be activated. 00168 // Also, find out whether you meet the conditions to be entered, or simply 00169 // if the given key matches (one of) yours: 00170 // 00171 // Note: The virtual functions which were previously blank are now using 00172 // the volatile key that is passed in from the c-tor. So if you 00173 // want a blank *EntryConditions function, then you'll want to 00174 // override them. 00175 virtual void addEntryConditions (void); 00176 virtual void removeEntryConditions(void); 00177 int meetsEntryConditions (const UI_Event &event) const; 00178 virtual int isEntryCondition (UI_Keyboard key) const; 00179 00180 // Override this to handle transitory key presses, default implementation 00181 // does nothing. Return true if key was handled. The key is in 00182 // event.state.id and the keypress state is in event.state.data. 00183 virtual bool handleTransitoryKey(const UI_Event & /*event*/) 00184 { return false; } 00185 00186 // Called if the state needs to handle changes in op parameters 00187 virtual int hasOpNode(const OP_Node &/*node*/) const; 00188 virtual void handleOpNodeChange(OP_Node &/*node*/); 00189 virtual void handleOpUIChange(OP_Node &/*node*/); 00190 virtual void handleOpNetChange(OP_Network &/*net*/); 00191 virtual void handleOpNetClear(); 00192 00193 // See how you can handle a node being deleted. If it's an implicit 00194 // node we might be OK. Return 0 if we can handle it, -1 if we must be 00195 // exited or restarted from scratch. 00196 virtual int handleNodeDeleted(OP_Node &/*node*/); 00197 00198 // Set or get the "locate" flag, which determines whether we're interested 00199 // in locate events or not. 00200 void wantsLocates(int yesNo) { myFlags.wantlocate=yesNo; } 00201 virtual int hasLocates() const{ return myFlags.wantlocate;} 00202 virtual bool doesHandleLocates() const { return false; } 00203 00204 // Query some of the flags: 00205 int isPreempted() const { return myFlags.preempted; } 00206 int isBuilding () const { return myFlags.busybuild; } 00207 int isEntered(void) const { return myFlags.entered; } 00208 bool isConcealed(void) const{ return myFlags.concealed; } 00209 00210 int isGenerating() const { return myFlags.scratch; } 00211 int isGeneratingInline() const 00212 { return myFlags.scratch==BM_State::BM_INLINE; } 00213 int isRegenerating() const 00214 { return myFlags.scratch==BM_State::BM_REGENERATE; } 00215 00216 int isOverlay(void) const 00217 { 00218 return myFlags.entered & 00219 BM_SimpleState::BM_OVERLAY_ENTRY; 00220 } 00221 int isFullTime(void) const 00222 { 00223 return myFlags.entered & 00224 BM_SimpleState::BM_FULLTIME_ENTRY; 00225 } 00226 virtual int isModifier(void) const { return myFlags.modifier; } 00227 00228 // If a state generates a sop and displays it (eg. a hide sop), it 00229 // will want the state controller to ignore the change so the state 00230 // doesn't exit. 00231 virtual bool ignoreDisplayFlagChange() const { return false; } 00232 00233 // Return a pointer to the feel containing the extra buttons of the state. 00234 // If a state has no extra buttons, 0 will be returned. 00235 virtual int findPI(BM_OpHandleLink *pi) const; 00236 00237 // Find out if the state is inherently sticky whether entered FULLTIME or 00238 // not. Non-sticky (ie oneTime) states pop back to the view state after 00239 // they've completed an operation. A state is sticky by default. 00240 int isSticky(void) const { return myFlags.sticky; } 00241 00242 // Checks if and how an RMB menu can be popped up. Usually, when the state 00243 // is in building mode, the RMB menus are not allowed (since RMB is used 00244 // to complete building/drawing/selection). 00245 enum BM_RMBMenuPopupMode 00246 { 00247 BM_RMB_MENU_ALLOWED, // show the menu right away 00248 BM_RMB_MENU_DELAYED, // wait and show menu if mouse was not dragged 00249 BM_RMB_MENU_DENIED // don't show the menu at all 00250 }; 00251 virtual BM_RMBMenuPopupMode getRMBMenuPopupMode() const; 00252 00253 // Return this state's index in the list of states: 00254 int index(void) const { return myIndex; } 00255 void index(int idx) { myIndex = idx; } 00256 00257 // The name of this class: 00258 virtual const char *className(void) const; 00259 00260 const PI_StateTemplate &getTemplate() const { return myTemplate; } 00261 PI_StateTemplate &getTemplate() { return myTemplate; } 00262 00263 // Returns the icon name and label that should appear in the viewer 00264 // operation controls bar when we are in this state. The default 00265 // implementation extracts this information from the state template. 00266 virtual const char *getOperationBarIconName() const; 00267 virtual const char *getOperationBarLabel() const; 00268 00269 virtual void afterUndo(); 00270 00271 // The user can dynamically change the bindings from the textport 00272 // We need to refresh the current handle in the viewports 00273 // cause they could be affected. 00274 virtual void refreshBindings(int id, const char *op_type); 00275 virtual void refreshSettings(int id, const char *op_type); 00276 00277 virtual const char *replaceCursor(const char *newcursor); 00278 00279 // Return the help for this state in the string that's passed in. 00280 // (Note that custom states may override getHelp() to 00281 // provide help, even though there is no actual help file.) is_html 00282 // will be set to indicate if the help is in html or not. 00283 // NOTE: The help file may contain unexpanded hotkey variables. 00284 virtual void getHelp(UT_String &help_text, bool &is_html); 00285 00286 // Find all help file information, see FUSE:openHdoxURL(). 00287 virtual void getHelpDirAndNameOrUrl(UT_String &dir, 00288 UT_String &name, 00289 UT_String &url); 00290 00291 // Show persistent handles in this state? 00292 virtual bool showPersistent() const { return true; } 00293 00294 // Return true if we would like to receive an event intended for the 00295 // click-orienter but was not consumed by it. All normal states should 00296 // only want this event if they are overlay states. 00297 virtual bool wantFailedOrienterEvent() const { return isOverlay(); } 00298 00299 // Show the geometry of the selected operator in this state? 00300 virtual bool getShowSelectedOp() const { return true; } 00301 00302 // Reset and clear any remembered state data. Used mainly for states such 00303 // as view, which would like to home on world origin again, etc. 00304 virtual void resetStateForNew() { }; 00305 00306 protected: 00307 // The state might contain some geometry it wants to display, but may not 00308 // want it to be part of the main gdp. This method allows the state to 00309 // "sneak in" this special geometry that it might have (eg. a rubber band 00310 // when building curves). This method is called by DM_State::render(). 00311 virtual void doRender(RE_Render *r, short x, short y, int ghost); 00312 00313 // Make this a state that changes data or not (0 by default): 00314 void setModifier(int yn) { myFlags.modifier = yn; } 00315 00316 // Find out whether the general entry conditions for overlay states 00317 // are met (before you test for your specific key conditions). 00318 // The basic conditions are that: 00319 // - the event type is key up/down 00320 // - no mouse button is down 00321 // - we're not the current state 00322 // - the current state is not and overlay itself 00323 int meetsBasicEntryConditions(const UI_Event &e) const; 00324 00325 // Set the build flag, ie. whether we're actually building something now 00326 // or making changes to geometry that is linked to this state. 00327 virtual void setBuild(int onOff); 00328 00329 BM_StateFlags myFlags; // useful flags 00330 00331 static bool theDelayedSelectionEventIsValid; 00332 static UI_Event theDelayedSelectionEvent; 00333 00334 private: 00335 PI_StateTemplate &myTemplate; 00336 00337 UI_Keyboard myVolatileKey;// the key used for entry condition 00338 int myIndex; // index in the list of states 00339 00340 UT_String myCommandName; 00341 00342 bool myCursorPushed; 00343 }; 00344 00345 #endif
1.5.9