1 /* 2 * Copyright 2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "MultipleManipulatorState.h" 10 11 #include <stdio.h> 12 13 #include <AppDefs.h> 14 15 #include "Manipulator.h" 16 #include "StateView.h" 17 18 // constructor 19 MultipleManipulatorState::MultipleManipulatorState(StateView* view) 20 : ViewState(view), 21 fManipulators(24), 22 fCurrentManipulator(NULL), 23 fPreviousManipulator(NULL) 24 { 25 } 26 27 // destructor 28 MultipleManipulatorState::~MultipleManipulatorState() 29 { 30 DeleteManipulators(); 31 } 32 33 // #pragma mark - 34 35 // Init 36 void 37 MultipleManipulatorState::Init() 38 { 39 } 40 41 // Cleanup 42 void 43 MultipleManipulatorState::Cleanup() 44 { 45 } 46 47 // #pragma mark - 48 49 // Draw 50 void 51 MultipleManipulatorState::Draw(BView* into, BRect updateRect) 52 { 53 int32 count = fManipulators.CountItems(); 54 for (int32 i = 0; i < count; i++) { 55 Manipulator* manipulator = 56 (Manipulator*)fManipulators.ItemAtFast(i); 57 if (manipulator->Bounds().Intersects(updateRect)) 58 manipulator->Draw(into, updateRect); 59 } 60 } 61 62 // MessageReceived 63 bool 64 MultipleManipulatorState::MessageReceived(BMessage* message, 65 Command** _command) 66 { 67 int32 count = fManipulators.CountItems(); 68 for (int32 i = 0; i < count; i++) { 69 Manipulator* manipulator = 70 (Manipulator*)fManipulators.ItemAtFast(i); 71 if (manipulator->MessageReceived(message, _command)) 72 return true; 73 } 74 return false; 75 } 76 77 // #pragma mark - 78 79 // MouseDown 80 void 81 MultipleManipulatorState::MouseDown(BPoint where, uint32 buttons, uint32 clicks) 82 { 83 if (buttons & B_SECONDARY_MOUSE_BUTTON) { 84 _ShowContextMenu(where); 85 return; 86 } 87 88 if (clicks == 2 89 && fPreviousManipulator 90 && fManipulators.HasItem(fPreviousManipulator)) { 91 // valid double click (onto the same, still existing manipulator) 92 if (fPreviousManipulator->TrackingBounds(fView).Contains(where) 93 && fPreviousManipulator->DoubleClicked(where)) { 94 // TODO: eat the click here or wait for MouseUp? 95 fPreviousManipulator = NULL; 96 return; 97 } 98 } 99 100 int32 count = fManipulators.CountItems(); 101 for (int32 i = count - 1; i >= 0; i--) { 102 Manipulator* manipulator = 103 (Manipulator*)fManipulators.ItemAtFast(i); 104 if (manipulator->MouseDown(where)) { 105 fCurrentManipulator = manipulator; 106 break; 107 } 108 } 109 110 fView->SetMouseEventMask(B_POINTER_EVENTS, B_LOCK_WINDOW_FOCUS); 111 } 112 113 // MouseMoved 114 void 115 MultipleManipulatorState::MouseMoved(BPoint where, uint32 transit, 116 const BMessage* dragMessage) 117 { 118 if (fCurrentManipulator) { 119 // the mouse is currently pressed 120 fCurrentManipulator->MouseMoved(where); 121 122 } else { 123 // the mouse is currently NOT pressed 124 125 // call MouseOver on all manipulators 126 // until one feels responsible 127 int32 count = fManipulators.CountItems(); 128 bool updateCursor = true; 129 for (int32 i = 0; i < count; i++) { 130 Manipulator* manipulator = 131 (Manipulator*)fManipulators.ItemAtFast(i); 132 if (manipulator->TrackingBounds(fView).Contains(where) 133 && manipulator->MouseOver(where)) { 134 updateCursor = false; 135 break; 136 } 137 } 138 if (updateCursor) 139 _UpdateCursor(); 140 } 141 } 142 143 // MouseUp 144 Command* 145 MultipleManipulatorState::MouseUp() 146 { 147 Command* command = NULL; 148 if (fCurrentManipulator) { 149 command = fCurrentManipulator->MouseUp(); 150 fPreviousManipulator = fCurrentManipulator; 151 fCurrentManipulator = NULL; 152 } 153 return command; 154 } 155 156 // #pragma mark - 157 158 // ModifiersChanged 159 void 160 MultipleManipulatorState::ModifiersChanged(uint32 modifiers) 161 { 162 int32 count = fManipulators.CountItems(); 163 for (int32 i = 0; i < count; i++) { 164 Manipulator* manipulator = 165 (Manipulator*)fManipulators.ItemAtFast(i); 166 manipulator->ModifiersChanged(modifiers); 167 } 168 } 169 170 // HandleKeyDown 171 bool 172 MultipleManipulatorState::HandleKeyDown(uint32 key, uint32 modifiers, 173 Command** _command) 174 { 175 int32 count = fManipulators.CountItems(); 176 for (int32 i = 0; i < count; i++) { 177 Manipulator* manipulator = 178 (Manipulator*)fManipulators.ItemAtFast(i); 179 if (manipulator->HandleKeyDown(key, modifiers, _command)) 180 return true; 181 } 182 return false; 183 } 184 185 // HandleKeyUp 186 bool 187 MultipleManipulatorState::HandleKeyUp(uint32 key, uint32 modifiers, 188 Command** _command) 189 { 190 int32 count = fManipulators.CountItems(); 191 for (int32 i = 0; i < count; i++) { 192 Manipulator* manipulator = 193 (Manipulator*)fManipulators.ItemAtFast(i); 194 if (manipulator->HandleKeyUp(key, modifiers, _command)) 195 return true; 196 } 197 return false; 198 } 199 200 // #pragma mark - 201 202 // AddManipulator 203 bool 204 MultipleManipulatorState::AddManipulator(Manipulator* manipulator) 205 { 206 if (!manipulator) 207 return false; 208 209 if (fManipulators.AddItem((void*)manipulator)) { 210 manipulator->AttachedToView(fView); 211 fView->Invalidate(manipulator->Bounds()); 212 return true; 213 } 214 return false; 215 } 216 217 // RemoveManipulator 218 Manipulator* 219 MultipleManipulatorState::RemoveManipulator(int32 index) 220 { 221 Manipulator* manipulator = (Manipulator*)fManipulators.RemoveItem(index); 222 223 if (manipulator == fCurrentManipulator) 224 fCurrentManipulator = NULL; 225 226 if (manipulator) { 227 fView->Invalidate(manipulator->Bounds()); 228 manipulator->DetachedFromView(fView); 229 } 230 231 return manipulator; 232 } 233 234 // DeleteManipulators 235 void 236 MultipleManipulatorState::DeleteManipulators() 237 { 238 BRect dirty(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN); 239 240 int32 count = fManipulators.CountItems(); 241 for (int32 i = 0; i < count; i++) { 242 Manipulator* m = (Manipulator*)fManipulators.ItemAtFast(i); 243 dirty = dirty | m->Bounds(); 244 m->DetachedFromView(fView); 245 delete m; 246 } 247 fManipulators.MakeEmpty(); 248 fCurrentManipulator = NULL; 249 fPreviousManipulator = NULL; 250 251 fView->Invalidate(dirty); 252 _UpdateCursor(); 253 } 254 255 // CountManipulators 256 int32 257 MultipleManipulatorState::CountManipulators() const 258 { 259 return fManipulators.CountItems(); 260 } 261 262 // ManipulatorAt 263 Manipulator* 264 MultipleManipulatorState::ManipulatorAt(int32 index) const 265 { 266 return (Manipulator*)fManipulators.ItemAt(index); 267 } 268 269 // ManipulatorAtFast 270 Manipulator* 271 MultipleManipulatorState::ManipulatorAtFast(int32 index) const 272 { 273 return (Manipulator*)fManipulators.ItemAtFast(index); 274 } 275 276 // #pragma mark - 277 278 // _UpdateViewCursor 279 void 280 MultipleManipulatorState::_UpdateCursor() 281 { 282 if (fCurrentManipulator) 283 fCurrentManipulator->UpdateCursor(); 284 else 285 fView->SetViewCursor(B_CURSOR_SYSTEM_DEFAULT); 286 } 287 288 // _ShowContextMenu 289 void 290 MultipleManipulatorState::_ShowContextMenu(BPoint where) 291 { 292 int32 count = fManipulators.CountItems(); 293 for (int32 i = 0; i < count; i++) { 294 Manipulator* manipulator = 295 (Manipulator*)fManipulators.ItemAtFast(i); 296 if (manipulator->ShowContextMenu(where)) 297 return; 298 } 299 } 300 301 302