PageRenderTime 36ms CodeModel.GetById 14ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 0ms

/src/editor/C4PropertyDlg.cpp

https://bitbucket.org/randrian/openclonk2
C++ | 424 lines | 307 code | 39 blank | 78 comment | 35 complexity | c83d184d8e71c0e03c6b27ca8bfbc898 MD5 | raw file
Possible License(s): WTFPL, 0BSD, LGPL-2.1, CC-BY-3.0
  1/*
  2 * OpenClonk, http://www.openclonk.org
  3 *
  4 * Copyright (c) 1998-2000  Matthes Bender
  5 * Copyright (c) 2001, 2006  Peter Wortmann
  6 * Copyright (c) 2001  Sven Eberhardt
  7 * Copyright (c) 2005, 2007  G?nther Brammer
  8 * Copyright (c) 2006-2007  Armin Burgmeier
  9 * Copyright (c) 2009  Nicolas Hake
 10 * Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de
 11 *
 12 * Portions might be copyrighted by other authors who have contributed
 13 * to OpenClonk.
 14 *
 15 * Permission to use, copy, modify, and/or distribute this software for any
 16 * purpose with or without fee is hereby granted, provided that the above
 17 * copyright notice and this permission notice appear in all copies.
 18 * See isc_license.txt for full license and disclaimer.
 19 *
 20 * "Clonk" is a registered trademark of Matthes Bender.
 21 * See clonk_trademark_license.txt for full license.
 22 */
 23
 24/* Console mode dialog for object properties and script interface */
 25
 26#include <C4Include.h>
 27#include <C4PropertyDlg.h>
 28
 29#ifndef BIG_C4INCLUDE
 30#include <C4Console.h>
 31#include <C4Application.h>
 32#include <C4Object.h>
 33#include <C4Player.h>
 34#include <C4Game.h>
 35#include <C4PlayerList.h>
 36#include <C4GameObjects.h>
 37#endif
 38
 39#include <StdRegistry.h>
 40
 41#ifdef WITH_DEVELOPER_MODE
 42# include <C4DevmodeDlg.h>
 43# include <C4Language.h>
 44
 45# include <gtk/gtkentry.h>
 46# include <gtk/gtkvbox.h>
 47# include <gtk/gtktextview.h>
 48# include <gtk/gtkwindow.h>
 49# include <gtk/gtkscrolledwindow.h>
 50#endif
 51
 52#ifdef _WIN32
 53BOOL CALLBACK PropertyDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam)
 54	{
 55	switch (Msg)
 56		{
 57		//------------------------------------------------------------------------------------------------
 58		case WM_CLOSE:
 59			Console.PropertyDlg.Clear();
 60			break;
 61		//------------------------------------------------------------------------------------------------
 62		case WM_DESTROY:
 63			StoreWindowPosition(hDlg, "Property", Config.GetSubkeyPath("Console"), FALSE);
 64			break;
 65		//------------------------------------------------------------------------------------------------
 66		case WM_INITDIALOG:
 67      SendMessage(hDlg,DM_SETDEFID,(WPARAM)IDOK,(LPARAM)0);
 68			return TRUE;
 69		//------------------------------------------------------------------------------------------------
 70		case WM_COMMAND:
 71			// Evaluate command
 72			switch (LOWORD(wParam))
 73				{
 74				// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 75				case IDOK:
 76					// IDC_COMBOINPUT to Console.EditCursor.In()
 77					char buffer[16000];
 78					GetDlgItemText(hDlg,IDC_COMBOINPUT,buffer,16000);
 79					if (buffer[0])
 80						Console.EditCursor.In(buffer);
 81					return TRUE;
 82				// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 83				case IDC_BUTTONRELOADDEF:
 84					Game.ReloadDef( Console.PropertyDlg.idSelectedDef );
 85					return TRUE;
 86				// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 87				}
 88			return FALSE;
 89    //-----------------------------------------------------------------------------------------------
 90		}
 91	return FALSE;
 92	}
 93#endif
 94C4PropertyDlg::C4PropertyDlg()
 95	{
 96	Default();
 97	}
 98
 99C4PropertyDlg::~C4PropertyDlg()
100	{
101	Clear();
102
103#ifdef WITH_DEVELOPER_MODE
104	if(vbox != NULL)
105	{
106		g_signal_handler_disconnect(G_OBJECT(C4DevmodeDlg::GetWindow()), handlerHide);
107		C4DevmodeDlg::RemovePage(vbox);
108		vbox = NULL;
109	}
110#endif // WITH_DEVELOPER_MODE
111	}
112
113bool C4PropertyDlg::Open()
114	{
115#ifdef _WIN32
116	if (hDialog) return true;
117	hDialog = CreateDialog(Application.GetInstance(),
118												 MAKEINTRESOURCE(IDD_PROPERTIES),
119												 Console.hWindow,
120												 (DLGPROC) PropertyDlgProc);
121	if (!hDialog) return false;
122	// Set text
123	SetWindowText(hDialog,LoadResStr("IDS_DLG_PROPERTIES"));
124	// Enable controls
125	EnableWindow( GetDlgItem(hDialog,IDOK), Console.Editing );
126	EnableWindow( GetDlgItem(hDialog,IDC_COMBOINPUT), Console.Editing );
127	EnableWindow( GetDlgItem(hDialog,IDC_BUTTONRELOADDEF), Console.Editing );
128	// Show window
129	RestoreWindowPosition(hDialog, "Property", Config.GetSubkeyPath("Console"));
130	SetWindowPos(hDialog,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE | SWP_NOMOVE);
131	ShowWindow(hDialog,SW_SHOWNORMAL | SW_SHOWNA);
132#else // _WIN32
133#ifdef WITH_DEVELOPER_MODE
134	if(vbox == NULL)
135	{
136		vbox = gtk_vbox_new(false, 6);
137
138		GtkWidget* scrolled_wnd = gtk_scrolled_window_new(NULL, NULL);
139		gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_wnd), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
140		gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrolled_wnd), GTK_SHADOW_IN);
141
142		textview = gtk_text_view_new();
143		entry = gtk_entry_new();
144
145		gtk_container_add(GTK_CONTAINER(scrolled_wnd), textview);
146		gtk_box_pack_start(GTK_BOX(vbox), scrolled_wnd, true, true, 0);
147		gtk_box_pack_start(GTK_BOX(vbox), entry, false, false, 0);
148
149		gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), false);
150		gtk_widget_set_sensitive(entry, Console.Editing);
151
152		gtk_widget_show_all(vbox);
153
154		C4DevmodeDlg::AddPage(vbox, GTK_WINDOW(Console.window), LoadResStr("IDS_DLG_PROPERTIES"));
155
156		g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(OnScriptActivate), this);
157
158		handlerHide = g_signal_connect(G_OBJECT(C4DevmodeDlg::GetWindow()), "hide", G_CALLBACK(OnWindowHide), this);
159	}
160
161	C4DevmodeDlg::SwitchPage(vbox);
162#endif // WITH_DEVELOPER_MODE
163#endif // _WIN32
164	Active = true;
165	return true;
166	}
167
168bool C4PropertyDlg::Update(C4ObjectList &rSelection)
169	{
170	if (!Active) return false;
171	// Set new selection
172	Selection.Copy(rSelection);
173	// Update input control
174	UpdateInputCtrl(Selection.GetObject());
175	// Update contents
176	return Update();
177	}
178
179bool IsObjectPointer(int iValue)
180	{
181  for (C4ObjectLink *cLnk=::Objects.First; cLnk; cLnk=cLnk->Next)
182		if (cLnk->Obj == (C4Object*) iValue)
183			return true;
184	return false;
185	}
186
187bool C4PropertyDlg::Update()
188	{
189	if (!Active) return false;
190
191	StdStrBuf Output;
192
193	idSelectedDef=C4ID_None;
194
195	// Compose info text by selected object(s)
196	switch (Selection.ObjectCount())
197		{
198		// No selection
199		case 0:
200			Output = LoadResStr("IDS_CNS_NOOBJECT");
201			break;
202		// One selected object
203		case 1:
204			{
205			C4Object *cobj=Selection.GetObject();
206			DecompileToBuf_Log<StdCompilerINIWrite>(mkNamingAdapt(*cobj, "Object"), &Output, "C4PropertyDlg::Update");
207			// Type
208			Output.AppendFormat(LoadResStr("IDS_CNS_TYPE"),cobj->GetName(),C4IdText(cobj->Def->id));
209			// Owner
210			if (ValidPlr(cobj->Owner))
211				{
212				Output.Append(LineFeed);
213				Output.AppendFormat(LoadResStr("IDS_CNS_OWNER"),::Players.Get(cobj->Owner)->GetName());
214				}
215			// Contents
216			if (cobj->Contents.ObjectCount())
217				{
218				Output.Append(LineFeed);
219				Output.Append(LoadResStr("IDS_CNS_CONTENTS"));
220				Output.Append(static_cast<const StdStrBuf &>(cobj->Contents.GetNameList(::Definitions)));
221				}
222			// Action
223			if (cobj->Action.pActionDef)
224				{
225				Output.Append(LineFeed);
226				Output.Append(LoadResStr("IDS_CNS_ACTION"));
227				Output.Append(cobj->Action.pActionDef->GetName());
228				}
229			// Locals
230			int cnt; bool fFirstLocal = true;
231			for (cnt=0; cnt < cobj->LocalNamed.GetAnzItems(); cnt++)
232				{
233				// Header
234				if (fFirstLocal) { Output.Append(LineFeed); Output.Append(LoadResStr("IDS_CNS_LOCALS")); fFirstLocal = false; }
235				Output.Append(LineFeed);
236				// Append name
237				Output.AppendFormat(" %s = ", cobj->LocalNamed.pNames->pNames[cnt]);
238				// write value
239				Output.Append(static_cast<const StdStrBuf &>(cobj->LocalNamed.pData[cnt].GetDataString()));
240				}
241			// Effects
242			for(C4Effect *pEffect = cobj->pEffects; pEffect; pEffect = pEffect->pNext)
243				{
244				// Header
245				if (pEffect == cobj->pEffects)
246					{
247					Output.Append(LineFeed);
248					Output.Append(LoadResStr("IDS_CNS_EFFECTS"));
249					}
250				Output.Append(LineFeed);
251				// Effect name
252				Output.AppendFormat(" %s: Interval %d", pEffect->Name, pEffect->iIntervall);
253				}
254			// Store selected def
255			idSelectedDef=cobj->id;
256			break;
257			}
258		// Multiple selected objects
259		default:
260			Output.Format(LoadResStr("IDS_CNS_MULTIPLEOBJECTS"),Selection.ObjectCount());
261			break;
262		}
263	// Update info edit control
264#ifdef _WIN32
265	int iLine = SendDlgItemMessage(hDialog,IDC_EDITOUTPUT,EM_GETFIRSTVISIBLELINE,(WPARAM)0,(LPARAM)0);
266	SetDlgItemText(hDialog,IDC_EDITOUTPUT,Output.getData());
267	SendDlgItemMessage(hDialog,IDC_EDITOUTPUT,EM_LINESCROLL,(WPARAM)0,(LPARAM)iLine);
268	UpdateWindow(GetDlgItem(hDialog,IDC_EDITOUTPUT));
269#else
270#ifdef WITH_DEVELOPER_MODE
271	GtkTextBuffer* buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview));
272	gtk_text_buffer_set_text(buffer, Output.getData(), -1);
273#endif
274#endif
275	return true;
276	}
277
278void C4PropertyDlg::Default()
279	{
280#ifdef _WIN32
281	hDialog=NULL;
282#else
283#ifdef WITH_DEVELOPER_MODE
284	vbox = NULL;
285#endif
286#endif
287	Active = false;
288	idSelectedDef=C4ID_None;
289	Selection.Default();
290	}
291
292void C4PropertyDlg::Clear()
293	{
294	Selection.Clear();
295#ifdef _WIN32
296	if (hDialog) DestroyWindow(hDialog); hDialog=NULL;
297#else
298#ifdef WITH_DEVELOPER_MODE
299	//if(vbox != NULL)
300	//	C4DevmodeDlg::SwitchPage(NULL);
301#endif
302#endif
303	Active = false;
304	}
305
306void C4PropertyDlg::UpdateInputCtrl(C4Object *pObj)
307	{
308	int cnt;
309#ifdef _WIN32
310	HWND hCombo = GetDlgItem(hDialog,IDC_COMBOINPUT);
311	// Remember old window text
312	char szLastText[500+1];
313	GetWindowText(hCombo,szLastText,500);
314	// Clear
315	SendMessage(hCombo,CB_RESETCONTENT,0,0);
316#else // _WIN32
317#ifdef WITH_DEVELOPER_MODE
318
319	GtkEntryCompletion* completion = gtk_entry_get_completion(GTK_ENTRY(entry));
320	GtkListStore* store;
321
322	// Uncouple list store from completion so that the completion is not
323	// notified for every row we are going to insert. This enhances
324	// performance significantly.
325	if(!completion)
326	{
327		completion = gtk_entry_completion_new();
328		store = gtk_list_store_new(1, G_TYPE_STRING);
329
330		gtk_entry_completion_set_text_column(completion, 0);
331		gtk_entry_set_completion(GTK_ENTRY(entry), completion);
332		g_object_unref(G_OBJECT(completion));
333	}
334	else
335	{
336		store = GTK_LIST_STORE(gtk_entry_completion_get_model(completion));
337		g_object_ref(G_OBJECT(store));
338		gtk_entry_completion_set_model(completion, NULL);
339	}
340
341	GtkTreeIter iter;
342	gtk_list_store_clear(store);
343#endif // WITH_DEVELOPER_MODE
344#endif // _WIN32
345
346	// add global and standard functions
347	for (C4AulFunc *pFn = ::ScriptEngine.GetFirstFunc(); pFn; pFn = ::ScriptEngine.GetNextFunc(pFn))
348		if (pFn->GetPublic())
349			{
350#ifdef _WIN32
351				SendMessage(hCombo,CB_ADDSTRING,0,(LPARAM)pFn->Name);
352#else
353#ifdef WITH_DEVELOPER_MODE
354			gtk_list_store_append(store, &iter);
355			gtk_list_store_set(store, &iter, 0, pFn->Name, -1);
356#endif
357#endif
358			}
359	// Add object script functions
360#ifdef _WIN32
361	bool fDivider = false;
362#endif
363	C4AulScriptFunc *pRef;
364	// Object script available
365	if (pObj && pObj->Def)
366		// Scan all functions
367		for (cnt=0; pRef=pObj->Def->Script.GetSFunc(cnt); cnt++)
368			// Public functions only
369			if (pRef->Access=AA_PUBLIC)
370				{
371#ifdef _WIN32
372				// Insert divider if necessary
373				if (!fDivider) { SendMessage(hCombo,CB_INSERTSTRING,0,(LPARAM)"----------"); fDivider=true; }
374#endif
375				// Add function
376#ifdef _WIN32
377				SendMessage(hCombo,CB_INSERTSTRING,0,(LPARAM)pRef->Name);
378#else
379#ifdef WITH_DEVELOPER_MODE
380				gtk_list_store_append(store, &iter);
381				gtk_list_store_set(store, &iter, 0, pRef->Name, -1);
382#endif
383#endif
384				}
385
386#ifdef _WIN32
387	// Restore old text
388	SetWindowText(hCombo,szLastText);
389#elif defined(WITH_DEVELOPER_MODE)
390	// Reassociate list store with completion
391	gtk_entry_completion_set_model(completion, GTK_TREE_MODEL(store));
392#endif
393	}
394
395void C4PropertyDlg::Execute()
396	{
397	if (!::Game.iTick35) Update();
398	}
399
400void C4PropertyDlg::ClearPointers(C4Object *pObj)
401	{
402	Selection.ClearPointers(pObj);
403	}
404
405#ifdef WITH_DEVELOPER_MODE
406// GTK+ callbacks
407void C4PropertyDlg::OnScriptActivate(GtkWidget* widget, gpointer data)
408{
409	const gchar* text = gtk_entry_get_text(GTK_ENTRY(widget));
410	if(text && text[0])
411		Console.EditCursor.In(text);
412}
413
414void C4PropertyDlg::OnWindowHide(GtkWidget* widget, gpointer user_data)
415{
416	static_cast<C4PropertyDlg*>(user_data)->Active = false;
417}
418
419/*void C4PropertyDlg::OnDestroy(GtkWidget* widget, gpointer data)
420{
421	static_cast<C4PropertyDlg*>(data)->window = NULL;
422	static_cast<C4PropertyDlg*>(data)->Active = false;
423}*/
424#endif