xref: /haiku/src/apps/mediaplayer/playlist/PlaylistWindow.cpp (revision 746cac055adc6ac3308c7bc2d29040fb95689cc9)
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 	// file
35 	M_PLAYLIST_OPEN			= 'open',
36 	M_PLAYLIST_SAVE			= 'save',
37 
38 	// edit
39 	M_PLAYLIST_EMPTY		= 'emty',
40 	M_PLAYLIST_RANDOMIZE	= 'rand'
41 };
42 
43 #define SPACE 5
44 
45 PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist,
46 		Controller* controller)
47 	: BWindow(frame, "Playlist", B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
48 		B_ASYNCHRONOUS_CONTROLS)
49 
50 	, fLocker(new RWLocker("command stack lock"))
51 	, fCommandStack(new CommandStack(fLocker))
52 	, fCommandStackListener(this)
53 {
54 	frame = Bounds();
55 
56 	_CreateMenu(frame);
57 		// will adjust frame to account for menubar
58 
59 	frame.right -= B_V_SCROLL_BAR_WIDTH;
60 	fListView = new PlaylistListView(frame, playlist, controller,
61 		fCommandStack);
62 
63 	BScrollView* scrollView = new BScrollView("playlist scrollview", fListView,
64 		B_FOLLOW_ALL_SIDES, 0, false, true, B_NO_BORDER);
65 
66 	fTopView = 	scrollView;
67 	AddChild(fTopView);
68 
69 	// small visual tweak
70 	if (BScrollBar* scrollBar = scrollView->ScrollBar(B_VERTICAL)) {
71 		// make it so the frame of the menubar is also the frame of
72 		// the scroll bar (appears to be)
73 		scrollBar->MoveBy(0, -1);
74 		scrollBar->ResizeBy(0, -(B_H_SCROLL_BAR_HEIGHT - 2));
75 	}
76 
77 	fCommandStack->AddListener(&fCommandStackListener);
78 	_ObjectChanged(fCommandStack);
79 }
80 
81 
82 PlaylistWindow::~PlaylistWindow()
83 {
84 	// give listeners a chance to detach themselves
85 	fTopView->RemoveSelf();
86 	delete fTopView;
87 
88 	fCommandStack->RemoveListener(&fCommandStackListener);
89 	delete fCommandStack;
90 	delete fLocker;
91 }
92 
93 
94 bool
95 PlaylistWindow::QuitRequested()
96 {
97 	Hide();
98 	return false;
99 }
100 
101 
102 void
103 PlaylistWindow::MessageReceived(BMessage* message)
104 {
105 	switch (message->what) {
106 		case B_MODIFIERS_CHANGED:
107 			if (LastMouseMovedView())
108 				PostMessage(message, LastMouseMovedView());
109 			break;
110 
111 		case B_UNDO:
112 			fCommandStack->Undo();
113 			break;
114 		case B_REDO:
115 			fCommandStack->Redo();
116 			break;
117 
118 		case MSG_OBJECT_CHANGED: {
119 			Notifier* notifier;
120 			if (message->FindPointer("object", (void**)&notifier) == B_OK)
121 				_ObjectChanged(notifier);
122 			break;
123 		}
124 
125 		case B_REFS_RECEIVED:
126 		case B_SIMPLE_DATA: {
127 			// only accept this message when it comes from the
128 			// player window, _not_ when it is dropped in this window
129 			// outside of the playlist!
130 			int32 appendIndex;
131 			if (message->FindInt32("append_index", &appendIndex) == B_OK) {
132 				fListView->RefsReceived(message, appendIndex);
133 			}
134 			break;
135 		}
136 
137 		case M_PLAYLIST_SAVE:
138 			if (!fSavePanel)
139 				fSavePanel = new BFilePanel(B_SAVE_PANEL);
140 			fSavePanel->Show();
141 			break;
142 		case B_SAVE_REQUESTED:
143 			printf("We are saving\n");
144 			//Use fListView and have a SaveToFile?
145 			break;
146 		case M_PLAYLIST_OPEN:
147 			if (!fOpenPanel)
148 				fOpenPanel = new BFilePanel(B_OPEN_PANEL);
149 			fOpenPanel->Show();
150 			break;
151 
152 		case M_PLAYLIST_EMPTY:
153 			fListView->RemoveAll();
154 			break;
155 		case M_PLAYLIST_RANDOMIZE:
156 			fListView->Randomize();
157 			break;
158 
159 		default:
160 			BWindow::MessageReceived(message);
161 			break;
162 	}
163 }
164 
165 
166 // #pragma mark -
167 
168 
169 void
170 PlaylistWindow::_CreateMenu(BRect& frame)
171 {
172 	frame.bottom = 15;
173 	BMenuBar* menuBar = new BMenuBar(frame, "main menu");
174 	BMenu* fileMenu = new BMenu("Playlist");
175 	menuBar->AddItem(fileMenu);
176 //	fileMenu->AddItem(new BMenuItem("Open"B_UTF8_ELLIPSIS,
177 //		new BMessage(M_PLAYLIST_OPEN), 'O'));
178 //	fileMenu->AddItem(new BMenuItem("Save"B_UTF8_ELLIPSIS,
179 //		new BMessage(M_PLAYLIST_SAVE), 'S'));
180 //	fileMenu->AddSeparatorItem();
181 	fileMenu->AddItem(new BMenuItem("Close",
182 		new BMessage(B_QUIT_REQUESTED), 'W'));
183 
184 	BMenu* editMenu = new BMenu("Edit");
185 	fUndoMI = new BMenuItem("Undo", new BMessage(B_UNDO), 'Z');
186 	editMenu->AddItem(fUndoMI);
187 	fRedoMI = new BMenuItem("Redo", new BMessage(B_REDO), 'Z', B_SHIFT_KEY);
188 	editMenu->AddItem(fRedoMI);
189 	editMenu->AddSeparatorItem();
190 	editMenu->AddItem(new BMenuItem("Make Empty",
191 		new BMessage(M_PLAYLIST_EMPTY), 'N'));
192 	editMenu->AddItem(new BMenuItem("Randomize",
193 		new BMessage(M_PLAYLIST_RANDOMIZE), 'R'));
194 	menuBar->AddItem(editMenu);
195 
196 	AddChild(menuBar);
197 	fileMenu->SetTargetForItems(this);
198 	editMenu->SetTargetForItems(this);
199 
200 	menuBar->ResizeToPreferred();
201 	frame = Bounds();
202 	frame.top = menuBar->Frame().bottom + 1;
203 }
204 
205 
206 // _ObjectChanged
207 void
208 PlaylistWindow::_ObjectChanged(const Notifier* object)
209 {
210 	if (object == fCommandStack) {
211 		// relable Undo item and update enabled status
212 		BString label("Undo");
213 		fUndoMI->SetEnabled(fCommandStack->GetUndoName(label));
214 		if (fUndoMI->IsEnabled())
215 			fUndoMI->SetLabel(label.String());
216 		else
217 			fUndoMI->SetLabel("<nothing to undo>");
218 
219 		// relable Redo item and update enabled status
220 		label.SetTo("Redo");
221 		fRedoMI->SetEnabled(fCommandStack->GetRedoName(label));
222 		if (fRedoMI->IsEnabled())
223 			fRedoMI->SetLabel(label.String());
224 		else
225 			fRedoMI->SetLabel("<nothing to redo>");
226 	}
227 }
228 
229