Author: aldeck Date: 2010-08-06 19:08:12 +0200 (Fri, 06 Aug 2010) New Revision: 37943 Changeset: http://dev.haiku-os.org/changeset/37943 Added: haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/IconButton.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/IconButton.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/PoseViewController.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/PoseViewController.h Modified: haiku/branches/developer/aldeck/tracker_layout/src/apps/tracker/Tracker.rdef haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/ContainerWindow.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/ContainerWindow.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/CountView.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/CountView.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/DeskWindow.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/DeskWindow.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/DesktopPoseView.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/DesktopPoseView.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/FilePanelPriv.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/FilePanelPriv.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/Jamfile haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/Model.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/Model.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/Navigator.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/Navigator.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/OpenWithWindow.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/OpenWithWindow.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/PoseView.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/PoseView.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/QueryContainerWindow.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/QueryContainerWindow.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/QueryPoseView.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/QueryPoseView.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/TitleView.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/TitleView.h haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/Tracker.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/TrackerIcons.rdef haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/VolumeWindow.cpp haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/VolumeWindow.h Log: * Introduced a new class PoseViewController that allows to centralize PoseView interaction with its user interface controls. The PoseView doesn't need to know how/what controls were created/layouted, be it owned by a window or a child view. It defines "listener methods" for controls that need updates. Done for CountView and BarberPole for which the semantic changed a bit. Will rework scrollbar updating in the same way (ExtentChanged instead of pulse polling). Before that, control creation was managed by TTracker/BContainerWindow and BPoseView "a la mode" spaghetti. Now the window owns all the controls (its child views) and fully controls how and when they are layouted. Everything now happens in the _Init method (ie: at construction). The code flow is now much more straight forward and less error prone. This opens lots of new possiblities for customizing precisely a BContainerWindow/BPoseView and it's UI. Work is still needed to simplify menu management though by moving those complex menus in separate classes. Note that PoseViewController design is still work in progress, as it was used to enforce a clean separation during the refactoring, some stuff don't really belong there, this will change as things consolidate in their new shape. * Reworked BContainerWindow/BPoseView init mechanism. This was needed to give full layout control to the window. Got rid of the BContainerWindow::NewPoseView / CreatePoseView mechanism. ContainerWindow now creates its PoseView by itself. Most BContainerWindow derivates now get the target model in the constructor. This will allow to make Init(). It is still externally triggered via a kRestoreState message (except for TFilePanel), the original author's intention was probably to make the restoring (~150ms per window here) execute in the window thread so that windows appear instantly. I will simplify that when reworking the persistency mechanism in a future commit where the model will be passed along with the message. * Actual BLayout'ing of libtracker: Removed all layouting manual setup / updating and fully use the layouting API for BPoseViews/BContainerWindow and all the derivates. Still missing is layouting of Status/Info/SettingsWindow (there's already one patch waiting from T.Murai). Some work has to be done regarding backward compatibility of FilePanel client customization (it works but suffers layouting bugs in some cases). Use B_AUTO_SIZE_LIMITS thus removing SetSizeLimits calls. * Temporarily disabled a few things that needed more work. Autoscrolling is disabled for now. Some menu management functions disabled. Folder icon disabled. Also disabled for now some BackgroundView code (used to decorate the border of the poseview in filepanels). * Removed BContainerWindow::ShouldAdd[Menu/ScrollBars/CountView] virtuals. This was used by derived BContainerWindows to tell their base class how to customize them. Now each derived window customize themselves in their _Init method, the base class doesn't have to know how. I plan to make BContainerWindow more abstract and maybe move its functionality to a BBrowserWindow as the lack of separation is a bit problematic right now. * BNavigator is fully BLayout'ed and uses HVIF IconButtons (code and artwork from stippi with slight changes). Funny note: Besides localization needs, this is what started everything, i just wanted to remove the ugly CalcNavigatorHeight method... Snowball effect! * Moved BContainerWindow:IsTrash/IsInTrash/IsPrintersDir methods were it belongs, in Model. Thus removing also the UpdateIfTrash method. * Moved BHScrollBar definition in PoseViewController.h/cpp for now. * Moved BContainerWindow::AddShortcuts to BDesktopPoseView::_AddShortcuts as it was its real meaning. In the current state, all the new layouting works though it sometimes isn't perfect, that's easily fixable now that the layout happens in one precise place for each kind of window. I'm having a layouting issue (bug?) with scrollbars, they are shifted by 1 pixel. Sorry it got so big, but the multiple interdependecies made it near impossible to do it more incrementally, and i don't like to commit broken code. Current code works well although there are a few known regressions and new bugs that i will squash in the next days. Special attention will be payed to the ContainerWindow/PoseView init sequence and state restoring and the differences between the new and old code. Destruction sequences have to be watched too. Some debugging output was left intentionally. A developer doc for Tracker is in construction. PoseView is now a lot less directly dependant on its BContainerWindow. A lot of things are now abstracted behind PoseViewController and more is yet to come. In the future it would be nice it it was possible to create a PoseView in an application just like any other control. PoseViewController is now also a step further in the direction of an extendable control system, though current stuff will benefit from it too, think integrated query panel, type ahead filtering ui, auto hiding scrollbars. Modified: haiku/branches/developer/aldeck/tracker_layout/src/apps/tracker/Tracker.rdef =================================================================== --- haiku/branches/developer/aldeck/tracker_layout/src/apps/tracker/Tracker.rdef 2010-08-06 13:22:25 UTC (rev 37942) +++ haiku/branches/developer/aldeck/tracker_layout/src/apps/tracker/Tracker.rdef 2010-08-06 17:08:12 UTC (rev 37943) @@ -9,7 +9,7 @@ internal = 0, short_info = "Tracker", long_info = "Tracker 5.2.1 ©1991-2001 Be, Inc.,\n" - "©2006-2009 Haiku, Inc." + "©2006-2010 Haiku, Inc." }; resource app_flags B_SINGLE_LAUNCH; @@ -66,3 +66,23 @@ $"040A0D0112000A0E0113000A0F0114000A100115000A11011600" }; +resource(201, "kActionBack") #'VICN' array { + $"6E636966040500020006023B739F3B784BBD5E1B3D59924AC607487DCF0093E2" + $"06FF25A0000200060237610B3A79B3BE3F6A3B117A4AE42248E57700D4FA9DFF" + $"1A6A0104014A010A072B3E3A2F3A364E364E463A463A4D030A00010010011784" + $"00040A020100000A0101001001157C0004" +}; + +resource(202, "kActionForward") #'VICN' array { + $"6E636966040500020006023B739F3B784BBD5E1B3D59924AC607487DCF0095E2" + $"06FF26A0000200060238B4E439E705BDE7313CB5034A8A3C48635C00D4FA9DFF" + $"1A6A0104014A010A074D3E3E4D3E462AC2232ABBC33E363E2F030A0001001001" + $"178400040A020100000A0101001001157C0004" +}; + +resource(203, "kActionUp") #'VICN' array { + $"6E636966040500020006023B739F3B784BBD5E1B3D59924AE607487DCF00FFBF" + $"44FFFF9806020006023A3F27371338BB135B3E3F414A364447949400FFD789FF" + $"E0860604014A010A07BF592D4DBE2746BE2746C48738C48738BE2731BE27030A" + $"0001001001178400040A020100000A0101001001157C0004" +}; \ No newline at end of file Modified: haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/ContainerWindow.cpp =================================================================== --- haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/ContainerWindow.cpp 2010-08-06 13:22:25 UTC (rev 37942) +++ haiku/branches/developer/aldeck/tracker_layout/src/kits/tracker/ContainerWindow.cpp 2010-08-06 17:08:12 UTC (rev 37943) @@ -45,7 +45,10 @@ #include <Directory.h> #include <Entry.h> #include <FindDirectory.h> +#include <GroupLayout.h> +#include <GroupLayoutBuilder.h> #include <InterfaceDefs.h> +#include <LayoutItem.h> #include <Locale.h> #include <MenuItem.h> #include <MenuBar.h> @@ -82,6 +85,7 @@ #include "Navigator.h" #include "NavMenu.h" #include "PoseView.h" +#include "PoseViewController.h" #include "QueryContainerWindow.h" #include "SelectionWindow.h" #include "TitleView.h" @@ -357,7 +361,7 @@ return; // we don't like the Trash icon (because it cannot be moved) - if (window->IsTrash() || window->IsPrintersDir()) + if (window->PoseView()->TargetModel()->IsTrash() || window->PoseView()->TargetModel()->IsPrintersDir()) return; uint32 buttons; @@ -534,33 +538,29 @@ // #pragma mark - -BContainerWindow::BContainerWindow(LockingList<BWindow> *list, - uint32 containerWindowFlags, - window_look look, window_feel feel, uint32 flags, uint32 workspace) - : BWindow(InitialWindowRect(feel), "TrackerWindow", look, feel, flags, - workspace), +BContainerWindow::BContainerWindow(Model* model, + LockingList<BWindow> *list, + uint32 containerWindowFlags, + window_look look, window_feel feel, uint32 flags, uint32 workspace) + : + BWindow(InitialWindowRect(feel), "TrackerWindow", look, feel, + flags | B_AUTO_UPDATE_SIZE_LIMITS | B_ASYNCHRONOUS_CONTROLS, workspace), + fCreationModel(model), fFileContextMenu(NULL), fWindowContextMenu(NULL), fDropContextMenu(NULL), fVolumeContextMenu(NULL), fDragContextMenu(NULL), fMoveToItem(NULL), - fCopyToItem(NULL), + fCopyToItem(NULL), fCreateLinkItem(NULL), fOpenWithItem(NULL), fNavigationItem(NULL), - fMenuBar(NULL), - fNavigator(NULL), + fController(NULL), fPoseView(NULL), fWindowList(list), - fAttrMenu(NULL), - fWindowMenu(NULL), - fFileMenu(NULL), fSelectionWindow(NULL), fTaskLoop(NULL), - fIsTrash(false), - fInTrash(false), - fIsPrinters(false), fContainerWindowFlags(containerWindowFlags), fBackgroundImage(NULL), fSavedZoomRect(0, 0, -1, -1), @@ -591,11 +591,6 @@ app->StartWatching(this, kDontMoveFilesToTrashChanged); app->Unlock(); } - - // ToDo: remove me once we have undo/redo menu items - // (that is, move them to AddShortcuts()) - AddShortcut('Z', B_COMMAND_KEY, new BMessage(B_UNDO), this); - AddShortcut('Z', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kRedo), this); } @@ -620,6 +615,8 @@ if (fSelectionWindow && fSelectionWindow->Lock()) fSelectionWindow->Quit(); + + delete fController; } @@ -696,9 +693,9 @@ fCreateLinkItem = NULL; } - if (fAttrMenu && !fAttrMenu->Supermenu()) { - delete fAttrMenu; - fAttrMenu = NULL; + if (Controller()->AttributeMenu() && !Controller()->AttributeMenu()->Supermenu()) { + // TODO delete Controller()->AttributeMenu(); + //Controller()->AttributeMenu() = NULL; } delete fFileContextMenu; @@ -734,60 +731,7 @@ } -BPoseView * -BContainerWindow::NewPoseView(Model *model, BRect rect, uint32 viewMode) -{ - return new BPoseView(model, rect, viewMode); -} - - void -BContainerWindow::UpdateIfTrash(Model *model) -{ - BEntry entry(model->EntryRef()); - - if (entry.InitCheck() == B_OK) { - fIsTrash = model->IsTrash(); - fInTrash = FSInTrashDir(model->EntryRef()); - fIsPrinters = FSIsPrintersDir(&entry); - } -} - - -void -BContainerWindow::CreatePoseView(Model *model) -{ - UpdateIfTrash(model); - BRect rect(Bounds()); - - TrackerSettings settings; - if (settings.SingleWindowBrowse() - && settings.ShowNavigator() - && model->IsDirectory()) - rect.top += BNavigator::CalcNavigatorHeight() + 1; - - rect.right -= B_V_SCROLL_BAR_WIDTH; - rect.bottom -= B_H_SCROLL_BAR_HEIGHT; - fPoseView = NewPoseView(model, rect, kListMode); - AddChild(fPoseView); - - if (settings.SingleWindowBrowse() - && model->IsDirectory() - && !fPoseView->IsFilePanel()) { - BRect rect(Bounds()); - rect.top = 0; - // The KeyMenuBar isn't attached yet, otherwise we'd use that to get the offset. - rect.bottom = BNavigator::CalcNavigatorHeight(); - fNavigator = new BNavigator(model, rect); - if (!settings.ShowNavigator()) - fNavigator->Hide(); - AddChild(fNavigator); - } - SetPathWatchingEnabled(settings.ShowNavigator() || settings.ShowFullPathInTitleBar()); -} - - -void BContainerWindow::AddContextMenus() { // create context sensitive menus @@ -855,52 +799,74 @@ fWindowContextMenu->SetFont(be_plain_font); AddWindowContextMenus(fWindowContextMenu); - fMenuBar->RemoveItem(fFileMenu); - delete fFileMenu; - fFileMenu = new BMenu(B_TRANSLATE("File")); - AddFileMenu(fFileMenu); - fMenuBar->AddItem(fFileMenu); + // TODO: disabled until menu system rework + /*Controller()->MenuBar()->RemoveItem(Controller()->FileMenu()); + delete Controller()->FileMenu(); + ///Controller()->FileMenu() = new BMenu(B_TRANSLATE("File")); + Controller()->AddFileMenu(Controller()->FileMenu()); + Controller()->MenuBar()->AddItem(Controller()->FileMenu()); - fMenuBar->RemoveItem(fWindowMenu); - delete fWindowMenu; - fWindowMenu = new BMenu(B_TRANSLATE("Window")); - fMenuBar->AddItem(fWindowMenu); - AddWindowMenu(fWindowMenu); + Controller()->MenuBar()->RemoveItem(Controller()->WindowMenu()); + delete Controller()->WindowMenu(); + //Controller()->WindowMenu() = new BMenu(B_TRANSLATE("Window")); + Controller()->MenuBar()->AddItem(Controller()->WindowMenu()); + Controller()->AddWindowMenu(Controller()->WindowMenu()); // just create the attribute, decide to add it later - fMenuBar->RemoveItem(fAttrMenu); - delete fAttrMenu; - fAttrMenu = new BMenu(B_TRANSLATE("Attributes")); - NewAttributeMenu(fAttrMenu); + Controller()->MenuBar()->RemoveItem(Controller()->AttributeMenu()); + delete Controller()->AttributeMenu(); + //Controller()->AttributeMenu() = new BMenu(B_TRANSLATE("Attributes")); + Controller()->NewAttributeMenu(Controller()->AttributeMenu()); if (PoseView()->ViewMode() == kListMode) - ShowAttributeMenu(); + Controller()->ShowAttributeMenu();*/ int32 selectCount = PoseView()->SelectionList()->CountItems(); - SetupOpenWithMenu(fFileMenu); + SetupOpenWithMenu(Controller()->FileMenu()); SetupMoveCopyMenus(selectCount ? PoseView()->SelectionList()->FirstItem()->TargetModel()->EntryRef() : NULL, - fFileMenu); + Controller()->FileMenu()); } void -BContainerWindow::Init(const BMessage *message) +BContainerWindow::_Init(const BMessage *message) { - float y_delta; - BEntry entry; - - ASSERT(fPoseView); - if (!fPoseView) + printf("(%p) BBrowserWindow::_Init \n", this); + + AutoLock<BWindow> lock(this); + if (!lock) return; + // create controls + fPoseView = new BPoseView(fCreationModel, kListMode); + fController = new PoseViewController(); + + Controller()->SetPoseView(fPoseView); + Controller()->CreateControls(fCreationModel); + + // layout controls + SetLayout(new BGroupLayout(B_HORIZONTAL)); + AddChild(BGroupLayoutBuilder(B_VERTICAL) + .Add(Controller()->MenuBar()) + .Add(Controller()->Navigator()) + .Add(Controller()->TitleView()) + .Add(BGroupLayoutBuilder(B_HORIZONTAL) + .Add(Controller()->PoseView()) + .Add(Controller()->VerticalScrollBar()) + ) + .Add(BGroupLayoutBuilder(B_HORIZONTAL) + .Add(Controller()->CountView()) + .Add(Controller()->HorizontalScrollBar(), 3.0f) + .SetInsets(0, 0, B_V_SCROLL_BAR_WIDTH, 0) + // avoid the window's resize handle + ) + ); + // deal with new unconfigured folders if (NeedsDefaultStateSetup()) SetUpDefaultState(); - - if (ShouldAddScrollBars()) - fPoseView->AddScrollBars(); - + fMoveToItem = new BMenuItem(new BNavMenu(B_TRANSLATE("Move to"), kMoveSelectionTo, this)); fCopyToItem = new BMenuItem(new BNavMenu(B_TRANSLATE("Copy to"), @@ -908,86 +874,67 @@ fCreateLinkItem = new BMenuItem(new BNavMenu(B_TRANSLATE("Create link"), kCreateLink, this), new BMessage(kCreateLink)); - TrackerSettings settings; + if (message) + RestoreState(*message); + else + RestoreState(); - if (ShouldAddMenus()) { - // add menu bar, menus and resize poseview to fit - fMenuBar = new BMenuBar(BRect(0, 0, Bounds().Width() + 1, 1), "MenuBar"); - fMenuBar->SetBorder(B_BORDER_FRAME); - AddMenus(); - AddChild(fMenuBar); - - y_delta = KeyMenuBar()->Bounds().Height() + 1; - - float navigatorDelta = 0; - - if (Navigator() && settings.ShowNavigator()) { - Navigator()->MoveTo(BPoint(0, y_delta)); - navigatorDelta = BNavigator::CalcNavigatorHeight() + 1; - } - - fPoseView->MoveTo(BPoint(0, navigatorDelta + y_delta)); - fPoseView->ResizeBy(0, -(y_delta)); - if (fPoseView->VScrollBar()) { - fPoseView->VScrollBar()->MoveBy(0, KeyMenuBar()->Bounds().Height()); - fPoseView->VScrollBar()->ResizeBy(0, -(KeyMenuBar()->Bounds().Height())); - } - - // add folder icon to menu bar - if (!TargetModel()->IsRoot() && !IsTrash()) { - float iconSize = fMenuBar->Bounds().Height() - 2; - if (iconSize < 16) - iconSize = 16; - float iconPosY = 1 + (fMenuBar->Bounds().Height() - 2 - iconSize) / 2; - BView *icon = new DraggableContainerIcon(BRect(Bounds().Width() - 4 - iconSize + 1, - iconPosY, Bounds().Width() - 4, iconPosY + iconSize - 1), - "ThisContainer", B_FOLLOW_RIGHT); - fMenuBar->AddChild(icon); - } - } else { - // add equivalents of the menu shortcuts to the menuless desktop window - AddShortcuts(); + Controller()->AddMenus(); + AddContextMenus(); + AddCommonShortcuts(); + + CheckScreenIntersect(); + // check window frame TODO: should be done after/in restorewindowstate + + Controller()->TitleView()->Reset(); + // TODO find a more elegant way for the titleview to get updates + + if (PoseView()->ViewMode() == kListMode) { + Controller()->ShowAttributeMenu(); + Controller()->MarkAttributeMenu(); } + + TrackerSettings settings; + if (settings.SingleWindowBrowse() + && fCreationModel->IsDirectory() + && !fPoseView->IsFilePanel()) { + + Controller()->SetControlVisible(Controller()->Navigator(), settings.ShowNavigator()); + } + + Controller()->TitleView()->Reset(); + // TODO look for a more robust way for the titleview to get updates - AddContextMenus(); - AddShortcut('T', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kDelete), PoseView()); - AddShortcut('K', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kCleanupAll), - PoseView()); - AddShortcut('Q', B_COMMAND_KEY | B_OPTION_KEY | B_SHIFT_KEY | B_CONTROL_KEY, - new BMessage(kQuitTracker)); + if (fBackgroundImage && PoseView()->ViewMode() != kListMode) + fBackgroundImage->Show(PoseView(), current_workspace()); - AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY, new BMessage(kOpenSelection), - PoseView()); + // add folder icon to menu bar + // TODO + /*if (!TargetModel()->IsRoot() && !TargetModel()->IsTrash()) { + float iconSize = 16;//Controller()->MenuBar()->Bounds().Height() - 2; + //if (iconSize < 16) + // iconSize = 16; + float iconPosY = 1 + (Controller()->MenuBar()->Bounds().Height() - 2 - iconSize) / 2; + BView *icon = new DraggableContainerIcon(BRect(Bounds().Width() - 4 - iconSize + 1, + iconPosY, Bounds().Width() - 4, iconPosY + iconSize - 1), + "ThisContainer", B_FOLLOW_RIGHT); + Controller()->MenuBar()->AddChild(icon); + }*/ - SetSingleWindowBrowseShortcuts(settings.SingleWindowBrowse()); -#if DEBUG - // add some debugging shortcuts - AddShortcut('D', B_COMMAND_KEY | B_CONTROL_KEY, new BMessage('dbug'), PoseView()); - AddShortcut('C', B_COMMAND_KEY | B_CONTROL_KEY, new BMessage('dpcc'), PoseView()); - AddShortcut('F', B_COMMAND_KEY | B_CONTROL_KEY, new BMessage('dpfl'), PoseView()); - AddShortcut('F', B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY, - new BMessage('dpfL'), PoseView()); -#endif - - if (message) - RestoreState(*message); + /* TODO + Controller()->SetScrollBarsEnabled(false); + BPoint origin; + if (ViewMode() == kListMode) + origin = fViewState->ListOrigin(); else - RestoreState(); + origin = fViewState->IconOrigin(); - if (ShouldAddMenus() && PoseView()->ViewMode() == kListMode) { - // for now only show attributes in list view - // eventually enable attribute menu to allow users to select - // using different attributes as titles in icon view modes - ShowAttributeMenu(); - } - MarkAttributeMenu(fAttrMenu); - CheckScreenIntersect(); + ScrollTo(origin);*/ + Controller()->UpdateScrollRange(); + /*Controller()->SetScrollBarsTo(origin); + Controller()->SetScrollBarsEnabled(true);*/ - if (fBackgroundImage && !dynamic_cast<BDeskWindow *>(this) - && PoseView()->ViewMode() != kListMode) - fBackgroundImage->Show(PoseView(), current_workspace()); - Show(); // done showing, turn the B_NO_WORKSPACE_ACTIVATION flag off; @@ -999,8 +946,6 @@ void BContainerWindow::RestoreState() { - SetSizeLimits(kContainerWidthMinLimit, 10000, kContainerWindowHeightLimit, 10000); - UpdateTitle(); WindowStateNodeOpener opener(this, false); @@ -1014,8 +959,6 @@ void BContainerWindow::RestoreState(const BMessage &message) { - SetSizeLimits(kContainerWidthMinLimit, 10000, kContainerWindowHeightLimit, 10000); - UpdateTitle(); RestoreWindowState(message); @@ -1066,8 +1009,9 @@ // use the default look SetTitle(TargetModel()->Name()); - if (Navigator()) - Navigator()->UpdateLocation(PoseView()->TargetModel(), kActionUpdatePath); + // TODO: strange shouldn't be done here, more like in a ModelChanged hook + if (Controller()->Navigator()) + Controller()->Navigator()->UpdateLocation(PoseView()->TargetModel(), kActionUpdatePath); } @@ -1118,7 +1062,7 @@ if (scroll != B_ORIGIN) PoseView()->ScrollBy(scroll.x, scroll.y); - PoseView()->UpdateScrollRange(); + Controller()->UpdateScrollRange(); PoseView()->ResetPosePlacementHint(); } @@ -1288,27 +1232,6 @@ } -bool -BContainerWindow::ShouldAddMenus() const -{ - return true; -} - - -bool -BContainerWindow::ShouldAddScrollBars() const -{ - return true; -} - - -bool -BContainerWindow::ShouldAddCountView() const -{ - return true; -} - - Model * BContainerWindow::TargetModel() const { @@ -1364,15 +1287,15 @@ ResizeTo(frame.Width(), frame.Height()); MoveTo(frame.LeftTop()); - PoseView()->DisableScrollBars(); + Controller()->SetScrollBarsEnabled(false); // scroll if there is an offset PoseView()->ScrollBy( extent.left - PoseView()->Bounds().left, extent.top - PoseView()->Bounds().top); - PoseView()->UpdateScrollRange(); - PoseView()->EnableScrollBars(); + Controller()->UpdateScrollRange(); + Controller()->SetScrollBarsEnabled(true); } @@ -1403,9 +1326,9 @@ if (message->HasMessage("state")) { BMessage state; message->FindMessage("state", &state); - Init(&state); + _Init(&state); } else - Init(); + _Init(); break; case kResizeToFit: @@ -1502,7 +1425,8 @@ if (StateNeedsSaving()) SaveState(false); - bool wasInTrash = IsTrash() || InTrash(); + bool wasInTrash = PoseView()->TargetModel()->IsTrash() + || PoseView()->TargetModel()->IsInTrash(); bool isRoot = PoseView()->TargetModel()->IsRoot(); // Switch dir and apply new state @@ -1512,22 +1436,20 @@ // Update PoseView PoseView()->SwitchDir(&ref, opener.StreamNode()); - fIsTrash = FSIsTrashDir(&entry); - fInTrash = FSInTrashDir(&ref); - - if (wasInTrash ^ (IsTrash() || InTrash()) + if (wasInTrash ^ (PoseView()->TargetModel()->IsTrash() + || PoseView()->TargetModel()->IsInTrash()) || isRoot != PoseView()->TargetModel()->IsRoot()) RepopulateMenus(); // Update Navigation bar - if (Navigator()) { + if (Controller()->Navigator() != NULL) { int32 action = kActionSet; if (message->FindInt32("action", &action) != B_OK) // Design problem? Why does FindInt32 touch // 'action' at all if he can't find it?? action = kActionSet; - Navigator()->UpdateLocation(PoseView()->TargetModel(), action); + Controller()->Navigator()->UpdateLocation(PoseView()->TargetModel(), action); } TrackerSettings settings; @@ -1612,23 +1534,22 @@ case kSingleWindowBrowseChanged: if (settings.SingleWindowBrowse() - && !Navigator() + && !Controller()->Navigator() && TargetModel()->IsDirectory() && !PoseView()->IsFilePanel() && !PoseView()->IsDesktopWindow()) { - BRect rect(Bounds()); - rect.top = KeyMenuBar()->Bounds().Height() + 1; - rect.bottom = rect.top + BNavigator::CalcNavigatorHeight(); - fNavigator = new BNavigator(TargetModel(), rect); - fNavigator->Hide(); - AddChild(fNavigator); + + Controller()->SetControlVisible(Controller()->Navigator(), settings.ShowNavigator()); SetPathWatchingEnabled(settings.ShowNavigator() || settings.ShowFullPathInTitleBar()); + } SetSingleWindowBrowseShortcuts(settings.SingleWindowBrowse()); break; case kShowNavigatorChanged: - ShowNavigator(settings.ShowNavigator()); + printf("kShowNavigatorChanged"); + Controller()->SetControlVisible(Controller()->Navigator(), + settings.ShowNavigator()); if (!IsPathWatchingEnabled() && settings.ShowNavigator()) SetPathWatchingEnabled(true); if (IsPathWatchingEnabled() && !(settings.ShowNavigator() || settings.ShowFullPathInTitleBar())) @@ -1645,9 +1566,9 @@ ? B_TRANSLATE("Delete") : B_TRANSLATE("Move to Trash")); } - // Deskbar doesn't have a menu bar, so check if there is fMenuBar - if (fMenuBar && fFileMenu) { - item = fFileMenu->FindItem(kMoveToTrash); + // Deskbar doesn't have a menu bar, so check if there is Controller()->MenuBar() + if (Controller()->MenuBar() && Controller()->FileMenu()) { + item = Controller()->FileMenu()->FindItem(kMoveToTrash); if (item) { item->SetLabel(dontMoveToTrash ? B_TRANSLATE("Delete") @@ -1812,256 +1733,38 @@ void -BContainerWindow::AddMenus() +BContainerWindow::AddCommonShortcuts() { - fFileMenu = new BMenu(B_TRANSLATE("File")); - AddFileMenu(fFileMenu); - fMenuBar->AddItem(fFileMenu); - fWindowMenu = new BMenu(B_TRANSLATE("Window")); - fMenuBar->AddItem(fWindowMenu); - AddWindowMenu(fWindowMenu); - // just create the attribute, decide to add it later - fAttrMenu = new BMenu(B_TRANSLATE("Attributes")); - NewAttributeMenu(fAttrMenu); -} + AddShortcut('Z', B_COMMAND_KEY, new BMessage(B_UNDO), this); + AddShortcut('Z', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kRedo), this); + + AddShortcut('T', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kDelete), PoseView()); + AddShortcut('K', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kCleanupAll), + PoseView()); + AddShortcut('Q', B_COMMAND_KEY | B_OPTION_KEY | B_SHIFT_KEY | B_CONTROL_KEY, + new BMessage(kQuitTracker)); + AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY, new BMessage(kOpenSelection), + PoseView()); + + TrackerSettings settings; + SetSingleWindowBrowseShortcuts(settings.SingleWindowBrowse()); -void -BContainerWindow::AddFileMenu(BMenu *menu) -{ - if (!PoseView()->IsFilePanel()) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Find" B_UTF8_ELLIPSIS), - new BMessage(kFindButton), 'F')); - } - - if (!TargetModel()->IsQuery() && !IsTrash() && !IsPrintersDir()) { - if (!PoseView()->IsFilePanel()) { - TemplatesMenu* templateMenu = new TemplatesMenu(PoseView(), - B_TRANSLATE("New")); - menu->AddItem(templateMenu); - templateMenu->SetTargetForItems(PoseView()); - } else { - menu->AddItem(new BMenuItem(B_TRANSLATE("New folder"), - new BMessage(kNewFolder), 'N')); - } - } - menu->AddSeparatorItem(); - - menu->AddItem(new BMenuItem(B_TRANSLATE("Open"), - new BMessage(kOpenSelection), 'O')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), - new BMessage(kGetInfo), 'I')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), - new BMessage(kEditItem), 'E')); - - if (IsTrash() || InTrash()) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Restore"), - new BMessage(kRestoreFromTrash))); - if (IsTrash()) { - // add as first item in menu - menu->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"), - new BMessage(kEmptyTrash)), 0); - menu->AddItem(new BSeparatorItem(), 1); - } - } else if (IsPrintersDir()) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Add printer"B_UTF8_ELLIPSIS), - new BMessage(kAddPrinter), 'N'), 0); - menu->AddItem(new BSeparatorItem(), 1); - menu->AddItem(new BMenuItem(B_TRANSLATE("Make active printer"), - new BMessage(kMakeActivePrinter))); - } else { - menu->AddItem(new BMenuItem(B_TRANSLATE("Duplicate"), - new BMessage(kDuplicateSelection), 'D')); - - menu->AddItem(new BMenuItem(TrackerSettings().DontMoveFilesToTrash() - ? B_TRANSLATE("Delete") : B_TRANSLATE("Move to Trash"), - new BMessage(kMoveToTrash), 'T')); - - menu->AddSeparatorItem(); - - // The "Move To", "Copy To", "Create Link" menus are inserted - // at this place, have a look at: - // BContainerWindow::SetupMoveCopyMenus() - } - - BMenuItem *cutItem = NULL, *copyItem = NULL, *pasteItem = NULL; - if (!IsPrintersDir()) { - menu->AddSeparatorItem(); - - menu->AddItem(cutItem = new BMenuItem(B_TRANSLATE("Cut"), - new BMessage(B_CUT), 'X')); - menu->AddItem(copyItem = new BMenuItem(B_TRANSLATE("Copy"), - new BMessage(B_COPY), 'C')); - menu->AddItem(pasteItem = new BMenuItem(B_TRANSLATE("Paste"), - new BMessage(B_PASTE), 'V')); - - menu->AddSeparatorItem(); - - menu->AddItem(new BMenuItem(B_TRANSLATE("Identify"), - new BMessage(kIdentifyEntry))); - BMenu* addOnMenuItem = new BMenu(B_TRANSLATE("Add-ons")); - addOnMenuItem->SetFont(be_plain_font); - menu->AddItem(addOnMenuItem); - } - - menu->SetTargetForItems(PoseView()); - if (cutItem) - cutItem->SetTarget(this); - if (copyItem) - copyItem->SetTarget(this); - if (pasteItem) - pasteItem->SetTarget(this); +#if DEBUG + // add some debugging shortcuts + AddShortcut('D', B_COMMAND_KEY | B_CONTROL_KEY, new BMessage('dbug'), PoseView()); + AddShortcut('C', B_COMMAND_KEY | B_CONTROL_KEY, new BMessage('dpcc'), PoseView()); + AddShortcut('F', B_COMMAND_KEY | B_CONTROL_KEY, new BMessage('dpfl'), PoseView()); + AddShortcut('F', B_COMMAND_KEY | B_CONTROL_KEY | B_OPTION_KEY, + new BMessage('dpfL'), PoseView()); +#endif } void -BContainerWindow::AddWindowMenu(BMenu *menu) -{ - BMenuItem *item; - - BMenu* iconSizeMenu = new BMenu(B_TRANSLATE("Icon view")); - - BMessage* message = new BMessage(kIconMode); - message->AddInt32("size", 32); - item = new BMenuItem(B_TRANSLATE("32 x 32"), message); - item->SetTarget(PoseView()); - iconSizeMenu->AddItem(item); - - message = new BMessage(kIconMode); - message->AddInt32("size", 40); - item = new BMenuItem(B_TRANSLATE("40 x 40"), message); - item->SetTarget(PoseView()); - iconSizeMenu->AddItem(item); - - message = new BMessage(kIconMode); - message->AddInt32("size", 48); - item = new BMenuItem(B_TRANSLATE("48 x 48"), message); - item->SetTarget(PoseView()); - iconSizeMenu->AddItem(item); - - message = new BMessage(kIconMode); - message->AddInt32("size", 64); - item = new BMenuItem(B_TRANSLATE("64 x 64"), message); - item->SetTarget(PoseView()); - iconSizeMenu->AddItem(item); - - iconSizeMenu->AddSeparatorItem(); - - message = new BMessage(kIconMode); - message->AddInt32("scale", 0); - item = new BMenuItem(B_TRANSLATE("Decrease size"), message, '-'); - item->SetTarget(PoseView()); - iconSizeMenu->AddItem(item); - - message = new BMessage(kIconMode); - message->AddInt32("scale", 1); - item = new BMenuItem(B_TRANSLATE("Increase size"), message, '+'); - item->SetTarget(PoseView()); - iconSizeMenu->AddItem(item); - - // A sub menu where the super item can be invoked. - menu->AddItem(iconSizeMenu); - iconSizeMenu->Superitem()->SetShortcut('1', B_COMMAND_KEY); - iconSizeMenu->Superitem()->SetMessage(new BMessage(kIconMode)); - iconSizeMenu->Superitem()->SetTarget(PoseView()); - - item = new BMenuItem(B_TRANSLATE("Mini icon view"), - new BMessage(kMiniIconMode), '2'); - item->SetTarget(PoseView()); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("List view"), - new BMessage(kListMode), '3'); - item->SetTarget(PoseView()); - menu->AddItem(item); - - menu->AddSeparatorItem(); - - item = new BMenuItem(B_TRANSLATE("Resize to fit"), - new BMessage(kResizeToFit), 'Y'); - item->SetTarget(this); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Clean up"), new BMessage(kCleanup), 'K'); - item->SetTarget(PoseView()); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Select"B_UTF8_ELLIPSIS), - new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY); - item->SetTarget(PoseView()); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Select all"), new BMessage(B_SELECT_ALL), - 'A'); - item->SetTarget(PoseView()); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Invert selection"), - new BMessage(kInvertSelection), 'S'); - item->SetTarget(PoseView()); - menu->AddItem(item); - - if (!IsTrash()) { - item = new BMenuItem(B_TRANSLATE("Open parent"), - new BMessage(kOpenParentDir), B_UP_ARROW); - item->SetTarget(PoseView()); - menu->AddItem(item); - } - - item = new BMenuItem(B_TRANSLATE("Close"), new BMessage(B_QUIT_REQUESTED), - 'W'); - item->SetTarget(this); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Close all in workspace"), - new BMessage(kCloseAllInWorkspace), 'Q'); - item->SetTarget(be_app); - menu->AddItem(item); - - menu->AddSeparatorItem(); - - item = new BMenuItem(B_TRANSLATE("Preferences" B_UTF8_ELLIPSIS), - new BMessage(kShowSettingsWindow)); - item->SetTarget(be_app); - menu->AddItem(item); -} - - -void -BContainerWindow::AddShortcuts() -{ - // add equivalents of the menu shortcuts to the menuless desktop window - ASSERT(!IsTrash()); - ASSERT(!PoseView()->IsFilePanel()); - ASSERT(!TargetModel()->IsQuery()); - - AddShortcut('X', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kCutMoreSelectionToClipboard), this); - AddShortcut('C', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kCopyMoreSelectionToClipboard), this); - AddShortcut('F', B_COMMAND_KEY, new BMessage(kFindButton), PoseView()); - AddShortcut('N', B_COMMAND_KEY, new BMessage(kNewFolder), PoseView()); - AddShortcut('O', B_COMMAND_KEY, new BMessage(kOpenSelection), PoseView()); - AddShortcut('I', B_COMMAND_KEY, new BMessage(kGetInfo), PoseView()); - AddShortcut('E', B_COMMAND_KEY, new BMessage(kEditItem), PoseView()); - AddShortcut('D', B_COMMAND_KEY, new BMessage(kDuplicateSelection), PoseView()); - AddShortcut('T', B_COMMAND_KEY, new BMessage(kMoveToTrash), PoseView()); - AddShortcut('K', B_COMMAND_KEY, new BMessage(kCleanup), PoseView()); - AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), PoseView()); - AddShortcut('S', B_COMMAND_KEY, new BMessage(kInvertSelection), PoseView()); - AddShortcut('A', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kShowSelectionWindow), PoseView()); - AddShortcut('G', B_COMMAND_KEY, new BMessage(kEditQuery), PoseView()); - // it is ok to add a global Edit query shortcut here, PoseView will - // filter out cases where selected pose is not a query - AddShortcut('U', B_COMMAND_KEY, new BMessage(kUnmountVolume), PoseView()); - AddShortcut(B_UP_ARROW, B_COMMAND_KEY, new BMessage(kOpenParentDir), PoseView()); - AddShortcut('O', B_COMMAND_KEY | B_CONTROL_KEY, new BMessage(kOpenSelectionWith), - PoseView()); -} - - -void BContainerWindow::MenusBeginning() { - if (!fMenuBar) + if (!Controller()->MenuBar()) return; if (CurrentMessage() && CurrentMessage()->what == B_MOUSE_DOWN) @@ -2072,16 +1775,16 @@ // File menu int32 selectCount = PoseView()->SelectionList()->CountItems(); - SetupOpenWithMenu(fFileMenu); + SetupOpenWithMenu(Controller()->FileMenu()); SetupMoveCopyMenus(selectCount - ? PoseView()->SelectionList()->FirstItem()->TargetModel()->EntryRef() : NULL, fFileMenu); + ? PoseView()->SelectionList()->FirstItem()->TargetModel()->EntryRef() : NULL, Controller()->FileMenu()); - UpdateMenu(fMenuBar, kMenuBarContext); + UpdateMenu(Controller()->MenuBar(), kMenuBarContext); - AddMimeTypesToMenu(fAttrMenu); + fController->AddMimeTypesToMenu(Controller()->AttributeMenu()); - if (IsPrintersDir()) { - EnableNamedMenuItem(fFileMenu, B_TRANSLATE("Make active printer"), + if (PoseView()->TargetModel()->IsPrintersDir()) { + EnableNamedMenuItem(Controller()->FileMenu(), B_TRANSLATE("Make active printer"), selectCount == 1); } } @@ -2372,7 +2075,10 @@ void BContainerWindow::SetupMoveCopyMenus(const entry_ref *item_ref, BMenu *parent) { - if (IsTrash() || InTrash() || IsPrintersDir() || !fMoveToItem || !fCopyToItem || !fCreateLinkItem) + if (PoseView()->TargetModel()->IsTrash() + || PoseView()->TargetModel()->IsInTrash() + || PoseView()->TargetModel()->IsPrintersDir() + || !fMoveToItem || !fCopyToItem || !fCreateLinkItem) return; // Grab the modifiers state since we use it twice @@ -2650,12 +2356,12 @@ menu->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), new BMessage(kEditItem), 'E')); - if (!IsTrash() && !InTrash() && !IsPrintersDir()) { + if (!PoseView()->TargetModel()->IsTrash() && !PoseView()->TargetModel()->IsInTrash() && !PoseView()->TargetModel()->IsPrintersDir()) { menu->AddItem(new BMenuItem(B_TRANSLATE("Duplicate"), new BMessage(kDuplicateSelection), 'D')); } - if (!IsTrash() && !InTrash()) { + if (!PoseView()->TargetModel()->IsTrash() && !PoseView()->TargetModel()->IsInTrash()) { menu->AddItem(new BMenuItem(TrackerSettings().DontMoveFilesToTrash() ? B_TRANSLATE("Delete") : B_TRANSLATE("Move to Trash"), new BMessage(kMoveToTrash), 'T')); @@ -2727,13 +2433,13 @@ // mode menu bool needSeparator = true; - if (IsTrash()) { + if (PoseView()->TargetModel()->IsTrash()) { menu->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"), new BMessage(kEmptyTrash))); - } else if (IsPrintersDir()) { + } else if (PoseView()->TargetModel()->IsPrintersDir()) { menu->AddItem(new BMenuItem(B_TRANSLATE("Add printer"B_UTF8_ELLIPSIS), new BMessage(kAddPrinter), 'N')); - } else if (InTrash()) + } else if (PoseView()->TargetModel()->IsInTrash()) needSeparator = false; else { TemplatesMenu* templateMenu = new TemplatesMenu(PoseView(), @@ -2757,7 +2463,7 @@ new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY)); menu->AddItem(new BMenuItem(B_TRANSLATE("Select all"), new BMessage(B_SELECT_ALL), 'A')); - if (!IsTrash()) { + if (!PoseView()->TargetModel()->IsTrash()) { menu->AddItem(new BMenuItem(B_TRANSLATE("Open parent"), new BMessage(kOpenParentDir), B_UP_ARROW)); } @@ -3109,343 +2815,6 @@ } -BMenuItem * -BContainerWindow::NewAttributeMenuItem(const char *label, const char *name, - int32 type, float width, int32 align, bool editable, bool statField) -{ - return NewAttributeMenuItem(label, name, type, NULL, width, align, - editable, statField); -} - - -BMenuItem * [... truncated: 6339 lines follow ...]