1 /* 2 * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>. 3 * All rights reserved. Distributed under the terms of the MIT License. 4 */ 5 6 #include <SplitView.h> 7 8 #include <stdio.h> 9 10 #include <Archivable.h> 11 #include <ControlLook.h> 12 #include <Cursor.h> 13 14 #include "SplitLayout.h" 15 16 17 BSplitView::BSplitView(enum orientation orientation, float spacing) 18 : 19 BView(NULL, 20 B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_INVALIDATE_AFTER_LAYOUT, 21 fSplitLayout = new BSplitLayout(orientation, spacing)) 22 { 23 SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR)); 24 } 25 26 27 BSplitView::BSplitView(BMessage* from) 28 : 29 BView(BUnarchiver::PrepareArchive(from)), 30 fSplitLayout(NULL) 31 { 32 BUnarchiver(from).Finish(); 33 } 34 35 36 BSplitView::~BSplitView() 37 { 38 } 39 40 41 void 42 BSplitView::SetInsets(float left, float top, float right, float bottom) 43 { 44 left = BControlLook::ComposeSpacing(left); 45 top = BControlLook::ComposeSpacing(top); 46 right = BControlLook::ComposeSpacing(right); 47 bottom = BControlLook::ComposeSpacing(bottom); 48 49 fSplitLayout->SetInsets(left, top, right, bottom); 50 } 51 52 53 void 54 BSplitView::SetInsets(float horizontal, float vertical) 55 { 56 horizontal = BControlLook::ComposeSpacing(horizontal); 57 vertical = BControlLook::ComposeSpacing(vertical); 58 fSplitLayout->SetInsets(horizontal, vertical, horizontal, vertical); 59 } 60 61 62 void 63 BSplitView::SetInsets(float insets) 64 { 65 insets = BControlLook::ComposeSpacing(insets); 66 fSplitLayout->SetInsets(insets, insets, insets, insets); 67 } 68 69 70 void 71 BSplitView::GetInsets(float* left, float* top, float* right, 72 float* bottom) const 73 { 74 fSplitLayout->GetInsets(left, top, right, bottom); 75 } 76 77 78 float 79 BSplitView::Spacing() const 80 { 81 return fSplitLayout->Spacing(); 82 } 83 84 85 void 86 BSplitView::SetSpacing(float spacing) 87 { 88 fSplitLayout->SetSpacing(spacing); 89 } 90 91 92 orientation 93 BSplitView::Orientation() const 94 { 95 return fSplitLayout->Orientation(); 96 } 97 98 99 void 100 BSplitView::SetOrientation(enum orientation orientation) 101 { 102 fSplitLayout->SetOrientation(orientation); 103 } 104 105 106 float 107 BSplitView::SplitterSize() const 108 { 109 return fSplitLayout->SplitterSize(); 110 } 111 112 113 void 114 BSplitView::SetSplitterSize(float size) 115 { 116 fSplitLayout->SetSplitterSize(size); 117 } 118 119 120 int32 121 BSplitView::CountItems() const 122 { 123 return fSplitLayout->CountItems(); 124 } 125 126 127 float 128 BSplitView::ItemWeight(int32 index) const 129 { 130 return fSplitLayout->ItemWeight(index); 131 } 132 133 134 float 135 BSplitView::ItemWeight(BLayoutItem* item) const 136 { 137 return fSplitLayout->ItemWeight(item); 138 } 139 140 141 void 142 BSplitView::SetItemWeight(int32 index, float weight, bool invalidateLayout) 143 { 144 fSplitLayout->SetItemWeight(index, weight, invalidateLayout); 145 } 146 147 148 void 149 BSplitView::SetItemWeight(BLayoutItem* item, float weight) 150 { 151 fSplitLayout->SetItemWeight(item, weight); 152 } 153 154 155 bool 156 BSplitView::IsCollapsible(int32 index) const 157 { 158 return fSplitLayout->IsCollapsible(index); 159 } 160 161 162 void 163 BSplitView::SetCollapsible(bool collapsible) 164 { 165 fSplitLayout->SetCollapsible(collapsible); 166 } 167 168 169 void 170 BSplitView::SetCollapsible(int32 index, bool collapsible) 171 { 172 fSplitLayout->SetCollapsible(index, collapsible); 173 } 174 175 176 void 177 BSplitView::SetCollapsible(int32 first, int32 last, bool collapsible) 178 { 179 fSplitLayout->SetCollapsible(first, last, collapsible); 180 } 181 182 183 bool 184 BSplitView::IsItemCollapsed(int32 index) const 185 { 186 return fSplitLayout->IsItemCollapsed(index); 187 } 188 189 190 void 191 BSplitView::SetItemCollapsed(int32 index, bool collapsed) 192 { 193 fSplitLayout->SetItemCollapsed(index, collapsed); 194 } 195 196 197 void 198 BSplitView::AddChild(BView* child, BView* sibling) 199 { 200 BView::AddChild(child, sibling); 201 } 202 203 204 bool 205 BSplitView::AddChild(BView* child, float weight) 206 { 207 return fSplitLayout->AddView(child, weight); 208 } 209 210 211 bool 212 BSplitView::AddChild(int32 index, BView* child, float weight) 213 { 214 return fSplitLayout->AddView(index, child, weight); 215 } 216 217 218 bool 219 BSplitView::AddChild(BLayoutItem* child) 220 { 221 return fSplitLayout->AddItem(child); 222 } 223 224 225 bool 226 BSplitView::AddChild(BLayoutItem* child, float weight) 227 { 228 return fSplitLayout->AddItem(child, weight); 229 } 230 231 232 bool 233 BSplitView::AddChild(int32 index, BLayoutItem* child, float weight) 234 { 235 return fSplitLayout->AddItem(index, child, weight); 236 } 237 238 239 void 240 BSplitView::Draw(BRect updateRect) 241 { 242 // draw the splitters 243 int32 draggedSplitterIndex = fSplitLayout->DraggedSplitter(); 244 int32 count = fSplitLayout->CountItems(); 245 for (int32 i = 0; i < count - 1; i++) { 246 BRect frame = fSplitLayout->SplitterItemFrame(i); 247 DrawSplitter(frame, updateRect, Orientation(), 248 draggedSplitterIndex == i); 249 } 250 } 251 252 253 void 254 BSplitView::MouseDown(BPoint where) 255 { 256 SetMouseEventMask(B_POINTER_EVENTS, 257 B_LOCK_WINDOW_FOCUS | B_SUSPEND_VIEW_FOCUS); 258 259 if (fSplitLayout->StartDraggingSplitter(where)) 260 Invalidate(); 261 } 262 263 264 void 265 BSplitView::MouseUp(BPoint where) 266 { 267 if (fSplitLayout->StopDraggingSplitter()) { 268 Relayout(); 269 Invalidate(); 270 } 271 } 272 273 274 void 275 BSplitView::MouseMoved(BPoint where, uint32 transit, const BMessage* message) 276 { 277 BCursor cursor(B_CURSOR_ID_SYSTEM_DEFAULT); 278 279 int32 splitterIndex = fSplitLayout->DraggedSplitter(); 280 281 if (splitterIndex >= 0 || fSplitLayout->IsAboveSplitter(where)) { 282 if (Orientation() == B_VERTICAL) 283 cursor = BCursor(B_CURSOR_ID_RESIZE_NORTH_SOUTH); 284 else 285 cursor = BCursor(B_CURSOR_ID_RESIZE_EAST_WEST); 286 } 287 288 if (splitterIndex >= 0) { 289 BRect oldFrame = fSplitLayout->SplitterItemFrame(splitterIndex); 290 if (fSplitLayout->DragSplitter(where)) { 291 Invalidate(oldFrame); 292 Invalidate(fSplitLayout->SplitterItemFrame(splitterIndex)); 293 } 294 } 295 296 SetViewCursor(&cursor, true); 297 } 298 299 300 void 301 BSplitView::SetLayout(BLayout* layout) 302 { 303 // not allowed 304 } 305 306 307 status_t 308 BSplitView::Archive(BMessage* into, bool deep) const 309 { 310 return BView::Archive(into, deep); 311 } 312 313 314 status_t 315 BSplitView::AllUnarchived(const BMessage* from) 316 { 317 status_t err = BView::AllUnarchived(from); 318 if (err == B_OK) { 319 fSplitLayout = dynamic_cast<BSplitLayout*>(GetLayout()); 320 if (!fSplitLayout && GetLayout()) 321 return B_BAD_TYPE; 322 else if (!fSplitLayout) 323 return B_ERROR; 324 } 325 return err; 326 } 327 328 329 BArchivable* 330 BSplitView::Instantiate(BMessage* from) 331 { 332 if (validate_instantiation(from, "BSplitView")) 333 return new BSplitView(from); 334 return NULL; 335 } 336 337 338 void 339 BSplitView::DrawSplitter(BRect frame, const BRect& updateRect, 340 enum orientation orientation, bool pressed) 341 { 342 _DrawDefaultSplitter(this, frame, updateRect, orientation, pressed); 343 } 344 345 346 void 347 BSplitView::_DrawDefaultSplitter(BView* view, BRect frame, 348 const BRect& updateRect, enum orientation orientation, bool pressed) 349 { 350 uint32 flags = pressed ? BControlLook::B_ACTIVATED : 0; 351 be_control_look->DrawSplitter(view, frame, updateRect, view->ViewColor(), 352 orientation, flags, 0); 353 } 354