xref: /haiku/src/apps/mediaplayer/playlist/PlaylistWindow.cpp (revision 1214ef1b2100f2b3299fc9d8d6142e46f70a4c3f)
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  */
8 #include "PlaylistWindow.h"
9 
10 #include <Menu.h>
11 #include <MenuBar.h>
12 #include <MenuItem.h>
13 #include <ScrollBar.h>
14 #include <ScrollView.h>
15 #include <String.h>
16 
17 #include "CommandStack.h"
18 #include "PlaylistListView.h"
19 #include "RWLocker.h"
20 
21 
22 PlaylistWindow::PlaylistWindow(BRect frame, Playlist* playlist,
23 		Controller* controller)
24 	: BWindow(frame, "Playlist", B_DOCUMENT_WINDOW_LOOK, B_NORMAL_WINDOW_FEEL,
25 		B_ASYNCHRONOUS_CONTROLS)
26 
27 	, fLocker(new RWLocker("command stack lock"))
28 	, fCommandStack(new CommandStack(fLocker))
29 	, fCommandStackListener(this)
30 {
31 	frame = Bounds();
32 
33 	_CreateMenu(frame);
34 
35 	frame.right -= B_V_SCROLL_BAR_WIDTH;
36 	fListView = new PlaylistListView(frame, playlist, controller,
37 		fCommandStack);
38 
39 	BScrollView* scrollView = new BScrollView("playlist scrollview",
40 		fListView, B_FOLLOW_ALL, 0, false, true, B_NO_BORDER);
41 
42 	fTopView = scrollView;
43 	AddChild(fTopView);
44 
45 	// small visual tweak
46 	if (BScrollBar* scrollBar = scrollView->ScrollBar(B_VERTICAL)) {
47 		// make it so the frame of the menubar is also the frame of
48 		// the scroll bar (appears to be)
49 		scrollBar->MoveBy(0, -1);
50 		scrollBar->ResizeBy(0, 1);
51 	}
52 
53 	fCommandStack->AddListener(&fCommandStackListener);
54 	_ObjectChanged(fCommandStack);
55 }
56 
57 
58 PlaylistWindow::~PlaylistWindow()
59 {
60 	// give listeners a chance to detach themselves
61 	fTopView->RemoveSelf();
62 	delete fTopView;
63 
64 	fCommandStack->RemoveListener(&fCommandStackListener);
65 	delete fCommandStack;
66 	delete fLocker;
67 }
68 
69 
70 bool
71 PlaylistWindow::QuitRequested()
72 {
73 	Hide();
74 	return false;
75 }
76 
77 
78 void
79 PlaylistWindow::MessageReceived(BMessage* message)
80 {
81 	switch (message->what) {
82 		case B_MODIFIERS_CHANGED:
83 			if (LastMouseMovedView())
84 				PostMessage(message, LastMouseMovedView());
85 			break;
86 
87 		case B_UNDO:
88 			fCommandStack->Undo();
89 			break;
90 		case B_REDO:
91 			fCommandStack->Redo();
92 			break;
93 
94 		case MSG_OBJECT_CHANGED: {
95 			Notifier* notifier;
96 			if (message->FindPointer("object", (void**)&notifier) == B_OK)
97 				_ObjectChanged(notifier);
98 			break;
99 		}
100 
101 		case B_REFS_RECEIVED:
102 		case B_SIMPLE_DATA: {
103 			// only accept this message when it comes from the
104 			// player window, _not_ when it is dropped in this window
105 			// outside of the playlist!
106 			int32 appendIndex;
107 			if (message->FindInt32("append_index", &appendIndex) == B_OK) {
108 				fListView->RefsReceived(message, appendIndex);
109 			}
110 			break;
111 		}
112 
113 		default:
114 			BWindow::MessageReceived(message);
115 			break;
116 	}
117 }
118 
119 
120 // #pragma mark -
121 
122 
123 void
124 PlaylistWindow::_CreateMenu(BRect& frame)
125 {
126 	frame.bottom = 15;
127 	BMenuBar* menuBar = new BMenuBar(frame, "main menu");
128 	BMenu* fileMenu = new BMenu("Playlist");
129 	menuBar->AddItem(fileMenu);
130 	// TODO add some items: "Open", "Save", "Make Empty"...
131 
132 	BMenu* editMenu = new BMenu("Edit");
133 	BMessage* message = new BMessage(B_UNDO);
134 	fUndoMI = new BMenuItem("Undo", message);
135 	editMenu->AddItem(fUndoMI);
136 	message = new BMessage(B_REDO);
137 	fRedoMI = new BMenuItem("Undo", message);
138 	editMenu->AddItem(fRedoMI);
139 	menuBar->AddItem(editMenu);
140 
141 	AddChild(menuBar);
142 	fileMenu->SetTargetForItems(this);
143 	editMenu->SetTargetForItems(this);
144 
145 	menuBar->ResizeToPreferred();
146 	frame = Bounds();
147 	frame.top = menuBar->Frame().bottom + 1;
148 }
149 
150 
151 // _ObjectChanged
152 void
153 PlaylistWindow::_ObjectChanged(const Notifier* object)
154 {
155 	if (object == fCommandStack) {
156 		// relable Undo item and update enabled status
157 		BString label("Undo");
158 		fUndoMI->SetEnabled(fCommandStack->GetUndoName(label));
159 		if (fUndoMI->IsEnabled())
160 			fUndoMI->SetLabel(label.String());
161 		else
162 			fUndoMI->SetLabel("<nothing to undo>");
163 
164 		// relable Redo item and update enabled status
165 		label.SetTo("Redo");
166 		fRedoMI->SetEnabled(fCommandStack->GetRedoName(label));
167 		if (fRedoMI->IsEnabled())
168 			fRedoMI->SetLabel(label.String());
169 		else
170 			fRedoMI->SetLabel("<nothing to redo>");
171 	}
172 }
173 
174