1/*
2 * Copyright 2015, Rene Gollent, rene@gollent.com.
3 * Distributed under the terms of the MIT License.
4 */
5#include "VariableEditWindow.h"
6
7#include <Button.h>
8#include <LayoutBuilder.h>
9#include <String.h>
10#include <StringView.h>
11
12#include "AppMessageCodes.h"
13#include "TableCellValueEditor.h"
14#include "Value.h"
15#include "ValueNode.h"
16
17
18enum {
19	MSG_VARIABLE_VALUE_CHANGED		= 'vavc'
20};
21
22
23VariableEditWindow::VariableEditWindow(Value* initialValue, ValueNode* node,
24	TableCellValueEditor* editor, BHandler* target)
25	:
26	BWindow(BRect(), "Edit value",
27		B_FLOATING_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
28	fCancelButton(NULL),
29	fSaveButton(NULL),
30	fTarget(target),
31	fNode(node),
32	fInitialValue(initialValue),
33	fNewValue(NULL),
34	fEditor(editor)
35{
36	fNode->AcquireReference();
37	fInitialValue->AcquireReference();
38	fEditor->AcquireReference();
39	fEditor->AddListener(this);
40}
41
42
43VariableEditWindow::~VariableEditWindow()
44{
45	fNode->ReleaseReference();
46	fInitialValue->ReleaseReference();
47	if (fNewValue != NULL)
48		fNewValue->ReleaseReference();
49
50	fEditor->RemoveListener(this);
51	fEditor->ReleaseReference();
52}
53
54
55VariableEditWindow*
56VariableEditWindow::Create(Value* initialValue, ValueNode* node,
57	TableCellValueEditor* editor, BHandler* target)
58{
59	VariableEditWindow* self = new VariableEditWindow(initialValue, node,
60		editor, target);
61
62	try {
63		self->_Init();
64	} catch (...) {
65		delete self;
66		throw;
67	}
68
69	return self;
70
71}
72
73
74void
75VariableEditWindow::_Init()
76{
77	BString label;
78	BString initialValue;
79	fInitialValue->ToString(initialValue);
80	label.SetToFormat("Initial value for '%s': %s\n",
81		fNode->Name().String(), initialValue.String());
82
83	BLayoutBuilder::Group<>(this, B_VERTICAL)
84		.SetInsets(B_USE_DEFAULT_SPACING)
85		.AddGroup(B_HORIZONTAL, 4.0f)
86			.Add(new BStringView("initialLabel", label))
87		.End()
88		.AddGroup(B_HORIZONTAL, 4.0f)
89			.Add(new BStringView("newLabel", "New value:"))
90			.Add(fEditor->GetView())
91		.End()
92		.AddGroup(B_HORIZONTAL, 4.0f)
93			.AddGlue()
94			.Add((fCancelButton = new BButton("Cancel",
95					new BMessage(B_QUIT_REQUESTED))))
96			.Add((fSaveButton = new BButton("Save",
97					new BMessage(MSG_WRITE_VARIABLE_VALUE))))
98		.End();
99
100	fCancelButton->SetTarget(this);
101	fSaveButton->SetTarget(this);
102	fSaveButton->MakeDefault(true);
103	fEditor->GetView()->MakeFocus(true);
104}
105
106
107void
108VariableEditWindow::Show()
109{
110	CenterOnScreen();
111	BWindow::Show();
112}
113
114
115bool
116VariableEditWindow::QuitRequested()
117{
118	fEditor->GetView()->RemoveSelf();
119
120	BMessenger messenger(fTarget);
121	messenger.SendMessage(MSG_VARIABLE_EDIT_WINDOW_CLOSED);
122
123	return BWindow::QuitRequested();
124}
125
126
127void
128VariableEditWindow::MessageReceived(BMessage* message)
129{
130	switch (message->what) {
131		case MSG_VARIABLE_VALUE_CHANGED:
132		{
133			Value* value;
134			if (message->FindPointer("value",
135					reinterpret_cast<void**>(&value)) == B_OK) {
136				if (fNewValue != NULL)
137					fNewValue->ReleaseReference();
138
139				fNewValue = value;
140			}
141			break;
142		}
143		case MSG_WRITE_VARIABLE_VALUE:
144		{
145			BMessage message(MSG_WRITE_VARIABLE_VALUE);
146			message.AddPointer("node", fNode);
147			message.AddPointer("value", fNewValue);
148
149			// acquire a reference on behalf of the target
150			BReference<Value> valueReference(fNewValue);
151			if (BMessenger(fTarget).SendMessage(&message) == B_OK) {
152				valueReference.Detach();
153				PostMessage(B_QUIT_REQUESTED);
154			}
155			break;
156		}
157		default:
158			BWindow::MessageReceived(message);
159			break;
160	}
161}
162
163
164void
165VariableEditWindow::TableCellEditBeginning()
166{
167}
168
169
170void
171VariableEditWindow::TableCellEditCancelled()
172{
173	PostMessage(B_QUIT_REQUESTED);
174}
175
176
177void
178VariableEditWindow::TableCellEditEnded(Value* newValue)
179{
180	BReference<Value> valueReference(newValue);
181	BMessage message(MSG_VARIABLE_VALUE_CHANGED);
182	message.AddPointer("value", newValue);
183	if (PostMessage(&message) == B_OK)
184		valueReference.Detach();
185}
186