Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / kits / tracker / Pose.cpp
blob6171bc3a0b1550d13b2babec7784e51e4baaaf53
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
36 #include <stdlib.h>
37 #include <string.h>
39 #include <Debug.h>
40 #include <NodeMonitor.h>
41 #include <Volume.h>
42 #include <fs_info.h>
44 #include "Attributes.h"
45 #include "Commands.h"
46 #include "FSClipboard.h"
47 #include "IconCache.h"
48 #include "Pose.h"
49 #include "PoseView.h"
52 int32
53 CalcFreeSpace(BVolume* volume)
55 off_t capacity = volume->Capacity();
56 if (capacity == 0)
57 return 100;
59 int32 percent
60 = static_cast<int32>(volume->FreeBytes() / (capacity / 100));
62 // warn below 20 MB of free space (if this is less than 10% of free space)
63 if (volume->FreeBytes() < 20 * 1024 * 1024 && percent < 10)
64 return -2 - percent;
65 return percent;
69 // SymLink handling:
70 // symlink pose uses the resolved model to retrieve the icon, if not broken
71 // everything else, like the attributes, etc. is retrieved directly from the
72 // symlink itself
73 BPose::BPose(Model* model, BPoseView* view, uint32 clipboardMode,
74 bool selected)
76 fModel(model),
77 fWidgetList(4, false),
78 fClipboardMode(clipboardMode),
79 fPercent(-1),
80 fSelectionTime(0),
81 fIsSelected(selected),
82 fHasLocation(false),
83 fNeedsSaveLocation(false),
84 fListModeInited(false),
85 fWasAutoPlaced(false),
86 fBrokenSymLink(false),
87 fBackgroundClean(false)
89 CreateWidgets(view);
91 if (model->IsVolume()) {
92 fs_info info;
93 dev_t device = model->NodeRef()->device;
94 BVolume* volume = new BVolume(device);
95 if (volume->InitCheck() == B_OK
96 && fs_stat_dev(device, &info) == B_OK) {
97 // Philosophy here:
98 // Bars go on all read/write volumes
99 // Exceptions: Not on CDDA
100 if (strcmp(info.fsh_name,"cdda") != 0
101 && !volume->IsReadOnly()) {
102 // The volume is ok and we want space bars on it
103 gPeriodicUpdatePoses.AddPose(this, view,
104 _PeriodicUpdateCallback, volume);
105 if (TrackerSettings().ShowVolumeSpaceBar())
106 fPercent = CalcFreeSpace(volume);
107 } else
108 delete volume;
109 } else
110 delete volume;
115 BPose::~BPose()
117 if (fModel->IsVolume()) {
118 // we might be registered for periodic updates
119 BVolume* volume = NULL;
120 if (gPeriodicUpdatePoses.RemovePose(this, (void**)&volume))
121 delete volume;
124 delete fModel;
128 void
129 BPose::CreateWidgets(BPoseView* poseView)
131 for (int32 index = 0; ; index++) {
132 BColumn* column = poseView->ColumnAt(index);
133 if (column == NULL)
134 break;
136 fWidgetList.AddItem(new BTextWidget(fModel, column, poseView));
141 BTextWidget*
142 BPose::AddWidget(BPoseView* poseView, BColumn* column)
144 BModelOpener opener(fModel);
145 if (fModel->InitCheck() != B_OK)
146 return NULL;
148 BTextWidget* widget = new BTextWidget(fModel, column, poseView);
149 fWidgetList.AddItem(widget);
151 return widget;
155 BTextWidget*
156 BPose::AddWidget(BPoseView* poseView, BColumn* column,
157 ModelNodeLazyOpener &opener)
159 opener.OpenNode();
160 if (fModel->InitCheck() != B_OK)
161 return NULL;
163 BTextWidget* widget = new BTextWidget(fModel, column, poseView);
164 fWidgetList.AddItem(widget);
166 return widget;
170 void
171 BPose::RemoveWidget(BPoseView*, BColumn* column)
173 int32 index;
174 BTextWidget* widget = WidgetFor(column->AttrHash(), &index);
175 if (widget != NULL)
176 delete fWidgetList.RemoveItemAt(index);
180 void
181 BPose::Commit(bool saveChanges, BPoint loc, BPoseView* poseView,
182 int32 poseIndex)
184 int32 count = fWidgetList.CountItems();
185 for (int32 index = 0; index < count; index++) {
186 BTextWidget* widget = fWidgetList.ItemAt(index);
187 if (widget != NULL && widget->IsActive()) {
188 widget->StopEdit(saveChanges, loc, poseView, this, poseIndex);
189 break;
195 inline bool
196 OneMouseUp(BTextWidget* widget, BPose* pose, BPoseView* poseView,
197 BColumn* column, BPoint poseLoc, BPoint where)
199 BRect rect;
200 if (poseView->ViewMode() == kListMode)
201 rect = widget->CalcClickRect(poseLoc, column, poseView);
202 else
203 rect = widget->CalcClickRect(pose->Location(poseView), NULL, poseView);
205 if (rect.Contains(where)) {
206 widget->MouseUp(rect, poseView, pose, where);
207 return true;
210 return false;
214 void
215 BPose::MouseUp(BPoint poseLoc, BPoseView* poseView, BPoint where, int32)
217 WhileEachTextWidget(this, poseView, OneMouseUp, poseLoc, where);
221 inline void
222 OneCheckAndUpdate(BTextWidget* widget, BPose*, BPoseView* poseView,
223 BColumn* column, BPoint poseLoc)
225 widget->CheckAndUpdate(poseLoc, column, poseView, true);
229 void
230 BPose::UpdateAllWidgets(int32, BPoint poseLoc, BPoseView* poseView)
232 if (poseView->ViewMode() != kListMode)
233 poseLoc = Location(poseView);
235 ASSERT(fModel->IsNodeOpen());
236 EachTextWidget(this, poseView, OneCheckAndUpdate, poseLoc);
240 void
241 BPose::UpdateWidgetAndModel(Model* resolvedModel, const char* attrName,
242 uint32 attrType, int32, BPoint poseLoc, BPoseView* poseView, bool visible)
244 if (poseView->ViewMode() != kListMode)
245 poseLoc = Location(poseView);
247 ASSERT(resolvedModel == NULL || resolvedModel->IsNodeOpen());
249 if (attrName != NULL) {
250 // pick up new attributes and find out if icon needs updating
251 if (resolvedModel->AttrChanged(attrName) && visible)
252 UpdateIcon(poseLoc, poseView);
254 // ToDo: the following code is wrong, because this sort of hashing
255 // may overlap and we get aliasing
256 uint32 attrHash = AttrHashString(attrName, attrType);
257 BTextWidget* widget = WidgetFor(attrHash);
258 if (widget != NULL) {
259 BColumn* column = poseView->ColumnFor(attrHash);
260 if (column != NULL)
261 widget->CheckAndUpdate(poseLoc, column, poseView, visible);
262 } else if (attrType == 0) {
263 // attribute got likely removed, so let's search the
264 // column for the matching attribute name
265 int32 count = fWidgetList.CountItems();
266 for (int32 i = 0; i < count; i++) {
267 BTextWidget* widget = fWidgetList.ItemAt(i);
268 BColumn* column = poseView->ColumnFor(widget->AttrHash());
269 if (column != NULL
270 && strcmp(column->AttrName(), attrName) == 0) {
271 widget->CheckAndUpdate(poseLoc, column, poseView, visible);
272 break;
276 } else {
277 // no attr name means check all widgets for stat info changes
279 // pick up stat changes
280 if (resolvedModel && resolvedModel->StatChanged()) {
281 if (resolvedModel->InitCheck() != B_OK)
282 return;
284 if (visible)
285 UpdateIcon(poseLoc, poseView);
288 // distribute stat changes
289 for (int32 index = 0; ; index++) {
290 BColumn* column = poseView->ColumnAt(index);
291 if (column == NULL)
292 break;
294 if (column->StatField()) {
295 BTextWidget* widget = WidgetFor(column->AttrHash());
296 if (widget != NULL)
297 widget->CheckAndUpdate(poseLoc, column, poseView, visible);
304 bool
305 BPose::_PeriodicUpdateCallback(BPose* pose, void* cookie)
307 return pose->UpdateVolumeSpaceBar((BVolume*)cookie);
311 bool
312 BPose::UpdateVolumeSpaceBar(BVolume* volume)
314 bool enabled = TrackerSettings().ShowVolumeSpaceBar();
315 if (!enabled) {
316 if (fPercent == -1)
317 return false;
319 fPercent = -1;
320 return true;
323 int32 percent = CalcFreeSpace(volume);
324 if (fPercent != percent) {
325 if (percent > 100)
326 fPercent = 100;
327 else
328 fPercent = percent;
330 return true;
333 return false;
337 void
338 BPose::UpdateIcon(BPoint poseLoc, BPoseView* poseView)
340 IconCache::sIconCache->IconChanged(ResolvedModel());
342 int32 iconSize = poseView->IconSizeInt();
344 BRect rect;
345 if (poseView->ViewMode() == kListMode) {
346 rect = CalcRect(poseLoc, poseView);
347 rect.left += kListOffset;
348 rect.right = rect.left + iconSize;
349 rect.top = rect.bottom - iconSize;
350 } else {
351 BPoint location = Location(poseView);
352 rect.left = location.x;
353 rect.top = location.y;
354 rect.right = rect.left + iconSize;
355 rect.bottom = rect.top + iconSize;
358 poseView->Invalidate(rect);
362 void
363 BPose::UpdateBrokenSymLink(BPoint poseLoc, BPoseView* poseView)
365 ASSERT(TargetModel()->IsSymLink());
366 ASSERT(TargetModel()->LinkTo() == NULL);
367 if (!TargetModel()->IsSymLink() || TargetModel()->LinkTo() != NULL)
368 return;
370 UpdateIcon(poseLoc, poseView);
374 void
375 BPose::UpdateWasBrokenSymlink(BPoint poseLoc, BPoseView* poseView)
377 if (!fModel->IsSymLink())
378 return;
380 if (fModel->LinkTo() != NULL) {
381 BEntry entry(fModel->EntryRef(), true);
382 if (entry.InitCheck() != B_OK) {
383 watch_node(fModel->LinkTo()->NodeRef(), B_STOP_WATCHING, poseView);
384 fModel->SetLinkTo(NULL);
385 UpdateIcon(poseLoc, poseView);
387 return;
390 poseView->CreateSymlinkPoseTarget(fModel);
391 UpdateIcon(poseLoc, poseView);
392 if (fModel->LinkTo() != NULL)
393 fModel->LinkTo()->CloseNode();
397 void
398 BPose::EditFirstWidget(BPoint poseLoc, BPoseView* poseView)
400 // find first editable widget
401 BColumn* column;
402 for (int32 i = 0; (column = poseView->ColumnAt(i)) != NULL; i++) {
403 BTextWidget* widget = WidgetFor(column->AttrHash());
405 if (widget != NULL && widget->IsEditable()) {
406 BRect bounds;
407 // ToDo:
408 // fold the three StartEdit code sequences into a cover call
409 if (poseView->ViewMode() == kListMode)
410 bounds = widget->CalcRect(poseLoc, column, poseView);
411 else
412 bounds = widget->CalcRect(Location(poseView), NULL, poseView);
414 widget->StartEdit(bounds, poseView, this);
415 break;
421 void
422 BPose::EditPreviousNextWidgetCommon(BPoseView* poseView, bool next)
424 bool found = false;
425 int32 delta = next ? 1 : -1;
426 for (int32 index = next ? 0 : poseView->CountColumns() - 1; ;
427 index += delta) {
428 BColumn* column = poseView->ColumnAt(index);
429 if (column == NULL) {
430 // out of columns
431 break;
434 BTextWidget* widget = WidgetFor(column->AttrHash());
435 if (widget == NULL) {
436 // no widget for this column, next
437 continue;
440 if (widget->IsActive()) {
441 poseView->CommitActivePose();
442 found = true;
443 continue;
446 if (found && column->Editable()) {
447 BRect bounds;
448 if (poseView->ViewMode() == kListMode) {
449 int32 poseIndex = poseView->IndexOfPose(this);
450 BPoint poseLoc(0, poseIndex* poseView->ListElemHeight());
451 bounds = widget->CalcRect(poseLoc, column, poseView);
452 } else
453 bounds = widget->CalcRect(Location(poseView), NULL, poseView);
455 widget->StartEdit(bounds, poseView, this);
456 break;
462 void
463 BPose::EditNextWidget(BPoseView* poseView)
465 EditPreviousNextWidgetCommon(poseView, true);
469 void
470 BPose::EditPreviousWidget(BPoseView* poseView)
472 EditPreviousNextWidgetCommon(poseView, false);
476 bool
477 BPose::PointInPose(const BPoseView* poseView, BPoint where) const
479 ASSERT(poseView->ViewMode() != kListMode);
481 BPoint location = Location(poseView);
483 if (poseView->ViewMode() == kIconMode) {
484 // check icon rect, then actual icon pixel
485 BRect rect(location, location);
486 rect.right += poseView->IconSizeInt() - 1;
487 rect.bottom += poseView->IconSizeInt() - 1;
489 if (rect.Contains(where)) {
490 return IconCache::sIconCache->IconHitTest(where - location,
491 ResolvedModel(), kNormalIcon, poseView->IconSize());
494 BTextWidget* widget = WidgetFor(poseView->FirstColumn()->AttrHash());
495 if (widget) {
496 float textWidth = ceilf(widget->TextWidth(poseView) + 1);
497 rect.left += (poseView->IconSizeInt() - textWidth) / 2;
498 rect.right = rect.left + textWidth;
501 rect.top = location.y + poseView->IconSizeInt();
502 rect.bottom = rect.top + poseView->FontHeight();
504 return rect.Contains(where);
507 // MINI_ICON_MODE rect calc
508 BRect rect(location, location);
509 rect.right += B_MINI_ICON + kMiniIconSeparator;
510 rect.bottom += poseView->IconPoseHeight();
511 BTextWidget* widget = WidgetFor(poseView->FirstColumn()->AttrHash());
512 if (widget != NULL)
513 rect.right += ceil(widget->TextWidth(poseView) + 1);
515 return rect.Contains(where);
519 bool
520 BPose::PointInPose(BPoint loc, const BPoseView* poseView, BPoint where,
521 BTextWidget** hitWidget) const
523 if (hitWidget)
524 *hitWidget = NULL;
526 // check intersection with icon
527 BRect rect;
528 rect.left = loc.x + kListOffset;
529 rect.right = rect.left + B_MINI_ICON;
530 rect.bottom = loc.y + poseView->ListElemHeight();
531 rect.top = rect.bottom - B_MINI_ICON;
532 if (rect.Contains(where))
533 return true;
535 for (int32 index = 0; ; index++) {
536 BColumn* column = poseView->ColumnAt(index);
537 if (column == NULL)
538 break;
540 BTextWidget* widget = WidgetFor(column->AttrHash());
541 if (widget != NULL
542 && widget->CalcClickRect(loc, column, poseView).Contains(where)) {
543 if (hitWidget != NULL)
544 *hitWidget = widget;
546 return true;
550 return false;
554 void
555 BPose::Draw(BRect rect, const BRect& updateRect, BPoseView* poseView,
556 BView* drawView, bool fullDraw, BPoint offset, bool selected)
558 // If the background wasn't cleared and Draw() is not called after
559 // having edited a name or similar (with fullDraw)
560 if (!fBackgroundClean && !fullDraw) {
561 fBackgroundClean = true;
562 poseView->Invalidate(rect);
563 return;
564 } else
565 fBackgroundClean = false;
567 bool directDraw = (drawView == poseView);
568 bool windowActive = poseView->Window()->IsActive();
569 bool showSelectionWhenInactive = poseView->fShowSelectionWhenInactive;
570 bool isDrawingSelectionRect = poseView->fIsDrawingSelectionRect;
572 ModelNodeLazyOpener modelOpener(fModel);
574 if (poseView->ViewMode() == kListMode) {
575 uint32 size = poseView->IconSizeInt();
576 BRect iconRect(rect);
577 iconRect.left += kListOffset;
578 iconRect.right = iconRect.left + size;
579 iconRect.top = iconRect.bottom - size;
580 if (updateRect.Intersects(iconRect)) {
581 iconRect.OffsetBy(offset);
582 DrawIcon(iconRect.LeftTop(), drawView, poseView->IconSize(),
583 directDraw, !windowActive && !showSelectionWhenInactive);
586 // draw text
587 int32 columnsToDraw = 1;
588 if (fullDraw)
589 columnsToDraw = poseView->CountColumns();
591 for (int32 index = 0; index < columnsToDraw; index++) {
592 BColumn* column = poseView->ColumnAt(index);
593 if (column == NULL)
594 break;
596 // if widget doesn't exist, create it
597 BTextWidget* widget = WidgetFor(column, poseView, modelOpener);
599 if (widget != NULL && widget->IsVisible()) {
600 BRect widgetRect(widget->ColumnRect(rect.LeftTop(), column,
601 poseView));
603 if (updateRect.Intersects(widgetRect)) {
604 BRect widgetTextRect(widget->CalcRect(rect.LeftTop(),
605 column, poseView));
607 bool selectDuringDraw = directDraw && selected
608 && windowActive;
610 if (index == 0 && selectDuringDraw) {
611 //draw with dark background to select text
612 drawView->PushState();
613 drawView->SetLowColor(0, 0, 0);
616 if (index == 0) {
617 widget->Draw(widgetRect, widgetTextRect,
618 column->Width(), poseView, drawView, selected,
619 fClipboardMode, offset, directDraw);
620 } else {
621 widget->Draw(widgetTextRect, widgetTextRect,
622 column->Width(), poseView, drawView, false,
623 fClipboardMode, offset, directDraw);
626 if (index == 0 && selectDuringDraw)
627 drawView->PopState();
628 else if (index == 0 && selected) {
629 if (windowActive || isDrawingSelectionRect) {
630 widgetTextRect.OffsetBy(offset);
631 drawView->InvertRect(widgetTextRect);
632 } else if (!windowActive
633 && showSelectionWhenInactive) {
634 widgetTextRect.OffsetBy(offset);
635 drawView->PushState();
636 drawView->SetDrawingMode(B_OP_BLEND);
637 drawView->SetHighColor(128, 128, 128, 255);
638 drawView->FillRect(widgetTextRect);
639 drawView->PopState();
645 } else {
646 // draw in icon mode
647 BPoint location(Location(poseView));
648 BPoint iconOrigin(location);
649 iconOrigin += offset;
651 DrawIcon(iconOrigin, drawView, poseView->IconSize(), directDraw,
652 !windowActive && !showSelectionWhenInactive);
654 BColumn* column = poseView->FirstColumn();
655 if (column == NULL)
656 return;
658 BTextWidget* widget = WidgetFor(column, poseView, modelOpener);
659 if (widget == NULL || !widget->IsVisible())
660 return;
662 rect = widget->CalcRect(location, NULL, poseView);
664 bool selectDuringDraw = directDraw && selected
665 && (poseView->IsDesktopWindow() || windowActive);
667 if (selectDuringDraw) {
668 // draw with dark background to select text
669 drawView->PushState();
670 drawView->SetLowColor(0, 0, 0);
673 widget->Draw(rect, rect, rect.Width(), poseView, drawView,
674 selected, fClipboardMode, offset, directDraw);
676 if (selectDuringDraw)
677 drawView->PopState();
678 else if (selected && directDraw) {
679 if (windowActive || isDrawingSelectionRect) {
680 rect.OffsetBy(offset);
681 drawView->InvertRect(rect);
682 } else if (!windowActive && showSelectionWhenInactive) {
683 drawView->PushState();
684 drawView->SetDrawingMode(B_OP_BLEND);
685 drawView->SetHighColor(128, 128, 128, 255);
686 drawView->FillRect(rect);
687 drawView->PopState();
694 void
695 BPose::DeselectWithoutErasingBackground(BRect, BPoseView* poseView)
697 ASSERT(poseView->ViewMode() != kListMode);
698 ASSERT(!IsSelected());
700 BPoint location(Location(poseView));
702 // draw icon directly
703 if (fPercent == -1)
704 DrawIcon(location, poseView, poseView->IconSize(), true);
705 else
706 UpdateIcon(location, poseView);
708 BColumn* column = poseView->FirstColumn();
709 if (column == NULL)
710 return;
712 BTextWidget* widget = WidgetFor(column->AttrHash());
713 if (widget == NULL || !widget->IsVisible())
714 return;
716 // just invalidate the background, don't draw anything
717 poseView->Invalidate(widget->CalcRect(location, NULL, poseView));
721 void
722 BPose::MoveTo(BPoint point, BPoseView* poseView, bool invalidate)
724 point.x = floorf(point.x);
725 point.y = floorf(point.y);
727 BRect oldBounds;
729 BPoint oldLocation = Location(poseView);
731 ASSERT(poseView->ViewMode() != kListMode);
732 if (point == oldLocation || poseView->ViewMode() == kListMode)
733 return;
735 if (invalidate)
736 oldBounds = CalcRect(poseView);
738 // might need to move a text view if we're active
739 if (poseView->ActivePose() == this) {
740 BView* border_view = poseView->FindView("BorderView");
741 if (border_view) {
742 border_view->MoveBy(point.x - oldLocation.x,
743 point.y - oldLocation.y);
747 float scale = 1.0;
748 if (poseView->ViewMode() == kIconMode) {
749 scale = poseView->IconSize() / 32.0;
751 fLocation.x = point.x / scale;
752 fLocation.y = point.y / scale;
754 fHasLocation = true;
755 fNeedsSaveLocation = true;
757 if (invalidate) {
758 poseView->Invalidate(oldBounds);
759 poseView->Invalidate(CalcRect(poseView));
764 BTextWidget*
765 BPose::ActiveWidget() const
767 for (int32 i = fWidgetList.CountItems(); i-- > 0;) {
768 BTextWidget* widget = fWidgetList.ItemAt(i);
769 if (widget->IsActive())
770 return widget;
773 return NULL;
777 BTextWidget*
778 BPose::WidgetFor(uint32 attr, int32* index) const
780 int32 count = fWidgetList.CountItems();
781 for (int32 i = 0; i < count; i++) {
782 BTextWidget* widget = fWidgetList.ItemAt(i);
783 if (widget->AttrHash() == attr) {
784 if (index != NULL)
785 *index = i;
787 return widget;
791 return NULL;
795 BTextWidget*
796 BPose::WidgetFor(BColumn* column, BPoseView* poseView,
797 ModelNodeLazyOpener &opener, int32* index)
799 BTextWidget* widget = WidgetFor(column->AttrHash(), index);
800 if (widget == NULL)
801 widget = AddWidget(poseView, column, opener);
803 return widget;
807 // the following method is deprecated
808 bool
809 BPose::TestLargeIconPixel(BPoint point) const
811 return IconCache::sIconCache->IconHitTest(point, ResolvedModel(),
812 kNormalIcon, B_LARGE_ICON);
816 void
817 BPose::DrawIcon(BPoint where, BView* view, icon_size which, bool direct,
818 bool drawUnselected)
820 if (fClipboardMode == kMoveSelectionTo) {
821 view->SetDrawingMode(B_OP_ALPHA);
822 view->SetHighColor(0, 0, 0, 64);
823 // set the level of transparency
824 view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY);
825 } else if (direct)
826 view->SetDrawingMode(B_OP_OVER);
828 IconCache::sIconCache->Draw(ResolvedModel(), view, where,
829 fIsSelected && !drawUnselected ? kSelectedIcon : kNormalIcon, which,
830 true);
832 if (fPercent != -1)
833 DrawBar(where, view, which);
837 void
838 BPose::DrawBar(BPoint where, BView* view, icon_size which)
840 view->PushState();
842 int32 size;
843 int32 barWidth;
844 int32 barHeight;
845 int32 yOffset;
846 if (which >= B_LARGE_ICON) {
847 size = which - 1;
848 barWidth = (int32)(7.0f / 32.0f * (float)which);
849 yOffset = 2;
850 barHeight = size - 4 - 2 * yOffset;
851 } else {
852 size = B_MINI_ICON;
853 barWidth = 4;
854 yOffset = 0;
855 barHeight = size - 4 - 2 * yOffset;
858 // the black shadowed line
859 view->SetHighColor(32, 32, 32, 92);
860 view->MovePenTo(BPoint(where.x + size, where.y + 1 + yOffset));
861 view->StrokeLine(BPoint(where.x + size, where.y + size - yOffset));
862 view->StrokeLine(BPoint(where.x + size - barWidth + 1,
863 where.y + size - yOffset));
865 view->SetDrawingMode(B_OP_ALPHA);
867 // the gray frame
868 view->SetHighColor(76, 76, 76, 192);
869 BRect rect(where.x + size - barWidth,where.y + yOffset,
870 where.x + size - 1,where.y + size - 1 - yOffset);
871 view->StrokeRect(rect);
873 // calculate bar height
874 int32 percent = fPercent > -1 ? fPercent : -2 - fPercent;
875 int32 barPos = int32(barHeight * percent / 100.0);
876 if (barPos < 0)
877 barPos = 0;
878 else if (barPos > barHeight)
879 barPos = barHeight;
881 // the free space bar
882 view->SetHighColor(TrackerSettings().FreeSpaceColor());
884 rect.InsetBy(1,1);
885 BRect bar(rect);
886 bar.bottom = bar.top + barPos - 1;
887 if (barPos > 0)
888 view->FillRect(bar);
890 // the used space bar
891 bar.top = bar.bottom + 1;
892 bar.bottom = rect.bottom;
893 view->SetHighColor(fPercent < -1
894 ? TrackerSettings().WarningSpaceColor()
895 : TrackerSettings().UsedSpaceColor());
896 view->FillRect(bar);
898 view->PopState();
902 void
903 BPose::DrawToggleSwitch(BRect, BPoseView*)
908 BPoint
909 BPose::Location(const BPoseView* poseView) const
911 float scale = 1.0;
912 if (poseView->ViewMode() == kIconMode)
913 scale = poseView->IconSize() / 32.0;
915 return BPoint(fLocation.x * scale, fLocation.y * scale);
919 void
920 BPose::SetLocation(BPoint point, const BPoseView* poseView)
922 float scale = 1.0;
923 if (poseView->ViewMode() == kIconMode)
924 scale = poseView->IconSize() / 32.0;
926 fLocation = BPoint(floorf(point.x / scale), floorf(point.y / scale));
927 if (isinff(fLocation.x) || isinff(fLocation.y))
928 debugger("BPose::SetLocation() - infinite location");
930 fHasLocation = true;
934 BRect
935 BPose::CalcRect(BPoint loc, const BPoseView* poseView, bool minimalRect) const
937 ASSERT(poseView->ViewMode() == kListMode);
939 BColumn* column = poseView->LastColumn();
940 BRect rect;
941 rect.left = loc.x;
942 rect.top = loc.y;
943 rect.right = loc.x + column->Offset() + column->Width();
944 rect.bottom = rect.top + poseView->ListElemHeight();
946 if (minimalRect) {
947 BTextWidget* widget = WidgetFor(poseView->FirstColumn()->AttrHash());
948 if (widget != NULL) {
949 rect.right = widget->CalcRect(loc, poseView->FirstColumn(),
950 poseView).right;
954 return rect;
958 BRect
959 BPose::CalcRect(const BPoseView* poseView) const
961 ASSERT(poseView->ViewMode() != kListMode);
963 BRect rect;
964 BPoint location = Location(poseView);
965 if (poseView->ViewMode() == kIconMode) {
966 rect.left = location.x;
967 rect.right = rect.left + poseView->IconSizeInt();
969 BTextWidget* widget = WidgetFor(poseView->FirstColumn()->AttrHash());
970 if (widget) {
971 float textWidth = ceilf(widget->TextWidth(poseView) + 1);
972 if (textWidth > poseView->IconSizeInt()) {
973 rect.left += (poseView->IconSizeInt() - textWidth) / 2;
974 rect.right = rect.left + textWidth;
978 rect.top = location.y;
979 rect.bottom = rect.top + poseView->IconPoseHeight();
980 } else {
981 // MINI_ICON_MODE rect calc
982 rect.left = location.x;
983 rect.top = location.y;
984 rect.right = rect.left + B_MINI_ICON + kMiniIconSeparator;
985 rect.bottom = rect.top + poseView->IconPoseHeight();
986 BTextWidget* widget = WidgetFor(poseView->FirstColumn()->AttrHash());
987 if (widget)
988 rect.right += ceil(widget->TextWidth(poseView) + 1);
991 return rect;
995 #if DEBUG
996 void
997 BPose::PrintToStream()
999 TargetModel()->PrintToStream();
1000 switch (fClipboardMode) {
1001 case kMoveSelectionTo:
1002 PRINT(("clipboardMode: Cut\n"));
1003 break;
1005 case kCopySelectionTo:
1006 PRINT(("clipboardMode: Copy\n"));
1007 break;
1009 default:
1010 PRINT(("clipboardMode: 0 - not in clipboard\n"));
1011 break;
1013 PRINT(("%sselected\n", IsSelected() ? "" : "not "));
1014 PRINT(("location %s x:%f y:%f\n", HasLocation() ? "" : "unknown ",
1015 HasLocation() ? fLocation.x : 0,
1016 HasLocation() ? fLocation.y : 0));
1017 PRINT(("%s autoplaced \n", WasAutoPlaced() ? "was" : "not"));
1019 #endif