1 /* 2 * Copyright 2007, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 * Fredrik Modéen <fredrik@modeen.se> 8 */ 9 10 #include "PlaylistWindow.h" 11 12 #include <stdio.h> 13 14 #include <Application.h> 15 #include <Roster.h> 16 #include <Path.h> 17 #include <Menu.h> 18 #include <MenuBar.h> 19 #include <MenuItem.h> 20 #include <ScrollBar.h> 21 #include <ScrollView.h> 22 #include <String.h> 23 #include <Box.h> 24 #include <Button.h> 25 #include <FilePanel.h> 26 27 #include "CommandStack.h" 28 #include "PlaylistListView.h" 29 #include "RWLocker.h" 30 31 #define DEBUG 1 32 33 enum { 34 M_PLAYLIST_OPEN = 'open', 35 M_PLAYLIST_SAVE = 'save', 36 M_PLAYLIST_EMPTY = 'emty' 37 }; 38 39 #define SPACE 5 40 41 PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist, 42 Controller* controller) 43 : BWindow(frame, "Playlist", B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL, 44 B_ASYNCHRONOUS_CONTROLS) 45 46 , fLocker(new RWLocker("command stack lock")) 47 , fCommandStack(new CommandStack(fLocker)) 48 , fCommandStackListener(this) 49 { 50 frame = Bounds(); 51 52 _CreateMenu(frame); 53 // will adjust frame to account for menubar 54 55 frame.right -= B_V_SCROLL_BAR_WIDTH; 56 fListView = new PlaylistListView(frame, playlist, controller, 57 fCommandStack); 58 59 BScrollView* scrollView = new BScrollView("playlist scrollview", fListView, 60 B_FOLLOW_ALL_SIDES, 0, false, true, B_NO_BORDER); 61 62 fTopView = scrollView; 63 AddChild(fTopView); 64 65 // small visual tweak 66 if (BScrollBar* scrollBar = scrollView->ScrollBar(B_VERTICAL)) { 67 // make it so the frame of the menubar is also the frame of 68 // the scroll bar (appears to be) 69 scrollBar->MoveBy(0, -1); 70 scrollBar->ResizeBy(0, 1); 71 } 72 73 fCommandStack->AddListener(&fCommandStackListener); 74 _ObjectChanged(fCommandStack); 75 } 76 77 78 PlaylistWindow::~PlaylistWindow() 79 { 80 // give listeners a chance to detach themselves 81 fTopView->RemoveSelf(); 82 delete fTopView; 83 84 fCommandStack->RemoveListener(&fCommandStackListener); 85 delete fCommandStack; 86 delete fLocker; 87 } 88 89 90 bool 91 PlaylistWindow::QuitRequested() 92 { 93 Hide(); 94 return false; 95 } 96 97 98 void 99 PlaylistWindow::MessageReceived(BMessage* message) 100 { 101 switch (message->what) { 102 case B_MODIFIERS_CHANGED: 103 if (LastMouseMovedView()) 104 PostMessage(message, LastMouseMovedView()); 105 break; 106 107 case B_UNDO: 108 fCommandStack->Undo(); 109 break; 110 case B_REDO: 111 fCommandStack->Redo(); 112 break; 113 114 case MSG_OBJECT_CHANGED: { 115 Notifier* notifier; 116 if (message->FindPointer("object", (void**)¬ifier) == B_OK) 117 _ObjectChanged(notifier); 118 break; 119 } 120 121 case B_REFS_RECEIVED: 122 case B_SIMPLE_DATA: { 123 // only accept this message when it comes from the 124 // player window, _not_ when it is dropped in this window 125 // outside of the playlist! 126 int32 appendIndex; 127 if (message->FindInt32("append_index", &appendIndex) == B_OK) { 128 fListView->RefsReceived(message, appendIndex); 129 } 130 break; 131 } 132 133 case M_PLAYLIST_SAVE: 134 if (!fSavePanel) 135 fSavePanel = new BFilePanel(B_SAVE_PANEL); 136 fSavePanel->Show(); 137 break; 138 case B_SAVE_REQUESTED: 139 printf("We are saving\n"); 140 //Use fListView and have a SaveToFile? 141 break; 142 case M_PLAYLIST_OPEN: 143 if (!fOpenPanel) 144 fOpenPanel = new BFilePanel(B_OPEN_PANEL); 145 fOpenPanel->Show(); 146 break; 147 case M_PLAYLIST_EMPTY: 148 break; 149 default: 150 BWindow::MessageReceived(message); 151 break; 152 } 153 } 154 155 156 // #pragma mark - 157 158 159 void 160 PlaylistWindow::_CreateMenu(BRect& frame) 161 { 162 frame.bottom = 15; 163 BMenuBar* menuBar = new BMenuBar(frame, "main menu"); 164 BMenu* fileMenu = new BMenu("Playlist"); 165 menuBar->AddItem(fileMenu); 166 // fileMenu->AddItem(new BMenuItem("Open"B_UTF8_ELLIPSIS, 167 // new BMessage(M_PLAYLIST_OPEN), 'O')); 168 // fileMenu->AddItem(new BMenuItem("Save"B_UTF8_ELLIPSIS, 169 // new BMessage(M_PLAYLIST_SAVE), 'S')); 170 // fileMenu->AddSeparatorItem(); 171 fileMenu->AddItem(new BMenuItem("Close", 172 new BMessage(B_QUIT_REQUESTED), 'W')); 173 174 BMenu* editMenu = new BMenu("Edit"); 175 fUndoMI = new BMenuItem("Undo", new BMessage(B_UNDO), 'Z'); 176 editMenu->AddItem(fUndoMI); 177 fRedoMI = new BMenuItem("Redo", new BMessage(B_REDO), 'Z', B_SHIFT_KEY); 178 editMenu->AddItem(fRedoMI); 179 editMenu->AddSeparatorItem(); 180 editMenu->AddItem(new BMenuItem("Make Empty", 181 new BMessage(M_PLAYLIST_EMPTY), 'N')); 182 menuBar->AddItem(editMenu); 183 184 AddChild(menuBar); 185 fileMenu->SetTargetForItems(this); 186 editMenu->SetTargetForItems(this); 187 188 menuBar->ResizeToPreferred(); 189 frame = Bounds(); 190 frame.top = menuBar->Frame().bottom + 1; 191 } 192 193 194 // _ObjectChanged 195 void 196 PlaylistWindow::_ObjectChanged(const Notifier* object) 197 { 198 if (object == fCommandStack) { 199 // relable Undo item and update enabled status 200 BString label("Undo"); 201 fUndoMI->SetEnabled(fCommandStack->GetUndoName(label)); 202 if (fUndoMI->IsEnabled()) 203 fUndoMI->SetLabel(label.String()); 204 else 205 fUndoMI->SetLabel("<nothing to undo>"); 206 207 // relable Redo item and update enabled status 208 label.SetTo("Redo"); 209 fRedoMI->SetEnabled(fCommandStack->GetRedoName(label)); 210 if (fRedoMI->IsEnabled()) 211 fRedoMI->SetLabel(label.String()); 212 else 213 fRedoMI->SetLabel("<nothing to redo>"); 214 } 215 } 216 217