1//////////////////////////////////////////////////////////////////////
2// This file is part of Remere's Map Editor
3//////////////////////////////////////////////////////////////////////
4// Remere's Map Editor is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Remere's Map Editor is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16//////////////////////////////////////////////////////////////////////
17
18#include "main.h"
19
20#include "properties_window.h"
21
22#include "gui_ids.h"
23#include "complexitem.h"
24#include "container_properties_window.h"
25
26#include <wx/grid.h>
27
28BEGIN_EVENT_TABLE(PropertiesWindow, wxDialog)
29EVT_BUTTON(wxID_OK, PropertiesWindow::OnClickOK)
30EVT_BUTTON(wxID_CANCEL, PropertiesWindow::OnClickCancel)
31
32EVT_BUTTON(ITEM_PROPERTIES_ADD_ATTRIBUTE, PropertiesWindow::OnClickAddAttribute)
33EVT_BUTTON(ITEM_PROPERTIES_REMOVE_ATTRIBUTE, PropertiesWindow::OnClickRemoveAttribute)
34
35EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, PropertiesWindow::OnNotebookPageChanged)
36
37EVT_GRID_CELL_CHANGED(PropertiesWindow::OnGridValueChanged)
38END_EVENT_TABLE()
39
40PropertiesWindow::PropertiesWindow(wxWindow* parent, const Map* map, const Tile* tile_parent, Item* item, wxPoint pos) :
41 ObjectPropertiesWindowBase(parent, "Item Properties", map, tile_parent, item, pos),
42 currentPanel(nullptr) {
43 ASSERT(edit_item);
44 notebook = newd wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(600, 300));
45
46 notebook->AddPage(createGeneralPanel(notebook), "Simple", true);
47 if (dynamic_cast<Container*>(item)) {
48 notebook->AddPage(createContainerPanel(notebook), "Contents");
49 }
50 notebook->AddPage(createAttributesPanel(notebook), "Advanced");
51
52 wxSizer* topSizer = newd wxBoxSizer(wxVERTICAL);
53 topSizer->Add(notebook, wxSizerFlags(1).DoubleBorder());
54
55 wxSizer* optSizer = newd wxBoxSizer(wxHORIZONTAL);
56 optSizer->Add(newd wxButton(this, wxID_OK, "OK"), wxSizerFlags(0).Center());
57 optSizer->Add(newd wxButton(this, wxID_CANCEL, "Cancel"), wxSizerFlags(0).Center());
58 topSizer->Add(optSizer, wxSizerFlags(0).Center().DoubleBorder());
59
60 SetSizerAndFit(topSizer);
61 Centre(wxBOTH);
62}
63
64PropertiesWindow::~PropertiesWindow() {
65 ;
66}
67
68void PropertiesWindow::Update() {
69 Container* container = dynamic_cast<Container*>(edit_item);
70 if (container) {
71 for (uint32_t i = 0; i < container->getVolume(); ++i) {
72 container_items[i]->setItem(container->getItem(i));
73 }
74 }
75 wxDialog::Update();
76}
77
78wxWindow* PropertiesWindow::createGeneralPanel(wxWindow* parent) {
79 wxPanel* panel = newd wxPanel(parent, ITEM_PROPERTIES_GENERAL_TAB);
80 wxFlexGridSizer* gridsizer = newd wxFlexGridSizer(2, 10, 10);
81 gridsizer->AddGrowableCol(1);
82
83 gridsizer->Add(newd wxStaticText(panel, wxID_ANY, "ID " + i2ws(edit_item->getID())));
84 gridsizer->Add(newd wxStaticText(panel, wxID_ANY, "\"" + wxstr(edit_item->getName()) + "\""));
85
86 gridsizer->Add(newd wxStaticText(panel, wxID_ANY, "Action ID"));
87 wxSpinCtrl* action_id_field = newd wxSpinCtrl(panel, wxID_ANY, i2ws(edit_item->getActionID()), wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, 0, 0xFFFF, edit_item->getActionID());
88 gridsizer->Add(action_id_field, wxSizerFlags(1).Expand());
89
90 gridsizer->Add(newd wxStaticText(panel, wxID_ANY, "Unique ID"));
91 wxSpinCtrl* unique_id_field = newd wxSpinCtrl(panel, wxID_ANY, i2ws(edit_item->getUniqueID()), wxDefaultPosition, wxSize(-1, 20), wxSP_ARROW_KEYS, 0, 0xFFFF, edit_item->getUniqueID());
92 gridsizer->Add(unique_id_field, wxSizerFlags(1).Expand());
93
94 panel->SetSizerAndFit(gridsizer);
95
96 return panel;
97}
98
99wxWindow* PropertiesWindow::createContainerPanel(wxWindow* parent) {
100 Container* container = (Container*)edit_item;
101 wxPanel* panel = newd wxPanel(parent, ITEM_PROPERTIES_CONTAINER_TAB);
102 wxSizer* topSizer = newd wxBoxSizer(wxVERTICAL);
103
104 wxSizer* gridSizer = newd wxGridSizer(6, 5, 5);
105
106 bool use_large_sprites = g_settings.getBoolean(Config::USE_LARGE_CONTAINER_ICONS);
107 for (uint32_t i = 0; i < container->getVolume(); ++i) {
108 Item* item = container->getItem(i);
109 ContainerItemButton* containerItemButton = newd ContainerItemButton(panel, use_large_sprites, i, edit_map, item);
110
111 container_items.push_back(containerItemButton);
112 gridSizer->Add(containerItemButton, wxSizerFlags(0));
113 }
114
115 topSizer->Add(gridSizer, wxSizerFlags(1).Expand());
116
117 /*
118 wxSizer* optSizer = newd wxBoxSizer(wxHORIZONTAL);
119 optSizer->Add(newd wxButton(panel, ITEM_PROPERTIES_ADD_ATTRIBUTE, "Add Item"), wxSizerFlags(0).Center());
120 // optSizer->Add(newd wxButton(panel, ITEM_PROPERTIES_REMOVE_ATTRIBUTE, "Remove Attribute"), wxSizerFlags(0).Center());
121 topSizer->Add(optSizer, wxSizerFlags(0).Center().DoubleBorder());
122 */
123
124 panel->SetSizer(topSizer);
125 return panel;
126}
127
128wxWindow* PropertiesWindow::createAttributesPanel(wxWindow* parent) {
129 wxPanel* panel = newd wxPanel(parent, wxID_ANY);
130 wxSizer* topSizer = newd wxBoxSizer(wxVERTICAL);
131
132 attributesGrid = newd wxGrid(panel, ITEM_PROPERTIES_ADVANCED_TAB, wxDefaultPosition, wxSize(-1, 160));
133 topSizer->Add(attributesGrid, wxSizerFlags(1).Expand());
134
135 wxFont time_font(*wxSWISS_FONT);
136 attributesGrid->SetDefaultCellFont(time_font);
137 attributesGrid->CreateGrid(0, 3);
138 attributesGrid->DisableDragRowSize();
139 attributesGrid->DisableDragColSize();
140 attributesGrid->SetSelectionMode(wxGrid::wxGridSelectRows);
141 attributesGrid->SetRowLabelSize(0);
142 // log->SetColLabelSize(0);
143 // log->EnableGridLines(false);
144 attributesGrid->EnableEditing(true);
145
146 attributesGrid->SetColLabelValue(0, "Key");
147 attributesGrid->SetColSize(0, 100);
148 attributesGrid->SetColLabelValue(1, "Type");
149 attributesGrid->SetColSize(1, 80);
150 attributesGrid->SetColLabelValue(2, "Value");
151 attributesGrid->SetColSize(2, 410);
152
153 // contents
154 ItemAttributeMap attrs = edit_item->getAttributes();
155 attributesGrid->AppendRows(attrs.size());
156 int i = 0;
157 for (ItemAttributeMap::iterator aiter = attrs.begin(); aiter != attrs.end(); ++aiter, ++i) {
158 SetGridValue(attributesGrid, i, aiter->first, aiter->second);
159 }
160
161 wxSizer* optSizer = newd wxBoxSizer(wxHORIZONTAL);
162 optSizer->Add(newd wxButton(panel, ITEM_PROPERTIES_ADD_ATTRIBUTE, "Add Attribute"), wxSizerFlags(0).Center());
163 optSizer->Add(newd wxButton(panel, ITEM_PROPERTIES_REMOVE_ATTRIBUTE, "Remove Attribute"), wxSizerFlags(0).Center());
164 topSizer->Add(optSizer, wxSizerFlags(0).Center().DoubleBorder());
165
166 panel->SetSizer(topSizer);
167
168 return panel;
169}
170
171void PropertiesWindow::SetGridValue(wxGrid* grid, int rowIndex, std::string label, const ItemAttribute& attr) {
172 wxArrayString types;
173 types.Add("Number");
174 types.Add("Float");
175 types.Add("Boolean");
176 types.Add("String");
177
178 grid->SetCellValue(rowIndex, 0, label);
179 switch (attr.type) {
180 case ItemAttribute::STRING: {
181 grid->SetCellValue(rowIndex, 1, "String");
182 grid->SetCellValue(rowIndex, 2, wxstr(*attr.getString()));
183 break;
184 }
185 case ItemAttribute::INTEGER: {
186 grid->SetCellValue(rowIndex, 1, "Number");
187 grid->SetCellValue(rowIndex, 2, i2ws(*attr.getInteger()));
188 grid->SetCellEditor(rowIndex, 2, new wxGridCellNumberEditor);
189 break;
190 }
191 case ItemAttribute::DOUBLE:
192 case ItemAttribute::FLOAT: {
193 grid->SetCellValue(rowIndex, 1, "Float");
194 wxString f;
195 f << *attr.getFloat();
196 grid->SetCellValue(rowIndex, 2, f);
197 grid->SetCellEditor(rowIndex, 2, new wxGridCellFloatEditor);
198 break;
199 }
200 case ItemAttribute::BOOLEAN: {
201 grid->SetCellValue(rowIndex, 1, "Boolean");
202 grid->SetCellValue(rowIndex, 2, *attr.getBoolean() ? "1" : "");
203 grid->SetCellRenderer(rowIndex, 2, new wxGridCellBoolRenderer);
204 grid->SetCellEditor(rowIndex, 2, new wxGridCellBoolEditor);
205 break;
206 }
207 default: {
208 grid->SetCellValue(rowIndex, 1, "Unknown");
209 grid->SetCellBackgroundColour(rowIndex, 1, *wxLIGHT_GREY);
210 grid->SetCellBackgroundColour(rowIndex, 2, *wxLIGHT_GREY);
211 grid->SetReadOnly(rowIndex, 1, true);
212 grid->SetReadOnly(rowIndex, 2, true);
213 break;
214 }
215 }
216 grid->SetCellEditor(rowIndex, 1, new wxGridCellChoiceEditor(types));
217}
218
219void PropertiesWindow::OnResize(wxSizeEvent& evt) {
220 /*
221 if(wxGrid* grid = (wxGrid*)currentPanel->FindWindowByName("AdvancedGrid")) {
222 int tWidth = 0;
223 for(int i = 0; i < 3; ++i)
224 tWidth += grid->GetColumnWidth(i);
225
226 int wWidth = grid->GetParent()->GetSize().GetWidth();
227
228 grid->SetColumnWidth(2, wWidth - 100 - 80);
229 }
230 */
231}
232
233void PropertiesWindow::OnNotebookPageChanged(wxNotebookEvent& evt) {
234 wxWindow* page = notebook->GetCurrentPage();
235
236 // TODO: Save
237
238 switch (page->GetId()) {
239 case ITEM_PROPERTIES_GENERAL_TAB: {
240 // currentPanel = createGeneralPanel(page);
241 break;
242 }
243 case ITEM_PROPERTIES_ADVANCED_TAB: {
244 // currentPanel = createAttributesPanel(page);
245 break;
246 }
247 default:
248 break;
249 }
250}
251
252void PropertiesWindow::saveGeneralPanel() {
253 ////
254}
255
256void PropertiesWindow::saveContainerPanel() {
257 ////
258}
259
260void PropertiesWindow::saveAttributesPanel() {
261 edit_item->clearAllAttributes();
262 for (int32_t rowIndex = 0; rowIndex < attributesGrid->GetNumberRows(); ++rowIndex) {
263 ItemAttribute attr;
264 wxString type = attributesGrid->GetCellValue(rowIndex, 1);
265 if (type == "String") {
266 attr.set(nstr(attributesGrid->GetCellValue(rowIndex, 2)));
267 } else if (type == "Float") {
268 double value;
269 if (attributesGrid->GetCellValue(rowIndex, 2).ToDouble(&value)) {
270 attr.set(value);
271 }
272 } else if (type == "Number") {
273 long value;
274 if (attributesGrid->GetCellValue(rowIndex, 2).ToLong(&value)) {
275 attr.set(static_cast<int32_t>(value));
276 }
277 } else if (type == "Boolean") {
278 attr.set(attributesGrid->GetCellValue(rowIndex, 2) == "1");
279 } else {
280 continue;
281 }
282 edit_item->setAttribute(nstr(attributesGrid->GetCellValue(rowIndex, 0)), attr);
283 }
284}
285
286void PropertiesWindow::OnGridValueChanged(wxGridEvent& event) {
287 if (event.GetCol() == 1) {
288 wxString newType = attributesGrid->GetCellValue(event.GetRow(), 1);
289 if (newType == event.GetString()) {
290 return;
291 }
292
293 ItemAttribute attr;
294 if (newType == "String") {
295 attr.set("");
296 } else if (newType == "Float") {
297 attr.set(0.0f);
298 } else if (newType == "Number") {
299 attr.set(0);
300 } else if (newType == "Boolean") {
301 attr.set(false);
302 }
303 SetGridValue(attributesGrid, event.GetRow(), nstr(attributesGrid->GetCellValue(event.GetRow(), 0)), attr);
304 }
305}
306
307void PropertiesWindow::OnClickOK(wxCommandEvent&) {
308 saveAttributesPanel();
309 EndModal(1);
310}
311
312void PropertiesWindow::OnClickAddAttribute(wxCommandEvent&) {
313 attributesGrid->AppendRows(1);
314 ItemAttribute attr(0);
315 SetGridValue(attributesGrid, attributesGrid->GetNumberRows() - 1, "", attr);
316}
317
318void PropertiesWindow::OnClickRemoveAttribute(wxCommandEvent&) {
319 wxArrayInt rowIndexes = attributesGrid->GetSelectedRows();
320 if (rowIndexes.Count() != 1) {
321 return;
322 }
323
324 int rowIndex = rowIndexes[0];
325 attributesGrid->DeleteRows(rowIndex, 1);
326}
327
328void PropertiesWindow::OnClickCancel(wxCommandEvent&) {
329 EndModal(0);
330}
331