PlaylistWindow.cpp revision 1b7f76bcfc37774f88e57a363f2f51263593f091
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
33enum {
34	M_PLAYLIST_OPEN		= 'open',
35	M_PLAYLIST_SAVE		= 'save',
36	M_PLAYLIST_EMPTY	= 'emty'
37};
38
39#define SPACE 5
40
41PlaylistWindow::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
78PlaylistWindow::~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
90bool
91PlaylistWindow::QuitRequested()
92{
93	Hide();
94	return false;
95}
96
97
98void
99PlaylistWindow::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**)&notifier) == 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
159void
160PlaylistWindow::_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
195void
196PlaylistWindow::_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