1 //////////////////////////////////////////////////////////////////////////
2 //
3 // pgAdmin III - PostgreSQL Tools
4 //
5 // Copyright (C) 2002 - 2016, The pgAdmin Development Team
6 // This software is released under the PostgreSQL Licence
7 //
8 // factory.cpp - Object classes factory
9 //
10 //////////////////////////////////////////////////////////////////////////
11 
12 // App headers
13 #include "pgAdmin3.h"
14 
15 #include "ctl/ctlMenuToolbar.h"
16 #include "schema/pgCollection.h"
17 #include "frm/menu.h"
18 
19 // wxWindows headers
20 #include <wx/imaglist.h>
21 
22 wxArrayPtrVoid *factoryArray = 0;
23 
24 #define FACTORY_OFFSET 100
25 
pgaFactory(const wxChar * tn,const wxChar * ns,const wxChar * nls,wxImage * img,wxImage * imgSm)26 pgaFactory::pgaFactory(const wxChar *tn, const wxChar *ns, const wxChar *nls, wxImage *img, wxImage *imgSm)
27 {
28 	if (!factoryArray)
29 		factoryArray = new wxArrayPtrVoid;
30 	id = factoryArray->GetCount() + FACTORY_OFFSET;
31 	factoryArray->Add(this);
32 	collectionFactory = 0;
33 	smallIconId = -1;
34 	typeName = (wxChar *)tn;
35 	if (ns)
36 		newString = (wxChar *)ns;
37 	else
38 		newString = typeName;
39 	if (nls)
40 		newLongString = (wxChar *)nls;
41 	else
42 		newLongString = newString;
43 	metaType = PGM_UNKNOWN;
44 
45 	if (img && img->IsOk())
46 	{
47 		image = *img;
48 		iconId = addIcon(img);
49 		if (imgSm && imgSm->IsOk())
50 			smallIconId = addIcon(imgSm);
51 	}
52 	else
53 		iconId = -1;
54 }
55 
56 
WantSmallIcon()57 bool pgaFactory::WantSmallIcon()
58 {
59 #ifdef __WXMSW__
60 	return true;
61 #else
62 	return false;
63 #endif
64 }
65 
GetIconId()66 int pgaFactory::GetIconId()
67 {
68 	if (WantSmallIcon() && smallIconId >= 0)
69 		return smallIconId;
70 
71 	return iconId;
72 }
73 
GetFactory(int id)74 pgaFactory *pgaFactory::GetFactory(int id)
75 {
76 	id -= FACTORY_OFFSET;
77 	if (id >= 0 && id < (int)factoryArray->GetCount())
78 		return (pgaFactory *)factoryArray->Item(id);;
79 
80 	return 0;
81 }
82 
83 
GetFactory(const wxString & name)84 pgaFactory *pgaFactory::GetFactory(const wxString &name)
85 {
86 	int i;
87 	pgaFactory *factory;
88 
89 	for (i = FACTORY_OFFSET ; (factory = GetFactory(i)) != 0 ; i++)
90 	{
91 		if (name.Matches(factory->GetTypeName()))
92 			return factory;
93 	}
94 	return 0;
95 }
96 
GetFactoryByMetaType(const int type)97 pgaFactory *pgaFactory::GetFactoryByMetaType(const int type)
98 {
99 	int i;
100 	pgaFactory *factory;
101 
102 	for (i = FACTORY_OFFSET ; (factory = GetFactory(i)) != 0 ; i++)
103 	{
104 		if (factory->GetMetaType() == type)
105 			return factory;
106 	}
107 	return 0;
108 }
109 
110 
111 #include "images/property.pngc"
112 #include "images/statistics.pngc"
113 
114 wxArrayPtrVoid *deferredImagesArray = 0;
115 
addIcon(wxImage * img)116 int pgaFactory::addIcon(wxImage *img)
117 {
118 	if (!imageList)
119 	{
120 		if (!deferredImagesArray)
121 		{
122 			//Setup the global imagelist
123 			deferredImagesArray = new wxArrayPtrVoid;
124 
125 			deferredImagesArray->Add(property_png_img);
126 			deferredImagesArray->Add(statistics_png_img);
127 		}
128 
129 		deferredImagesArray->Add(img);
130 
131 		return deferredImagesArray->GetCount() - 1;
132 	}
133 	else
134 	{
135 		wxBitmap bmp(*img);
136 		wxIcon *ico = new wxIcon();
137 		ico->CopyFromBitmap(bmp);
138 		return imageList->Add(*ico);
139 	}
140 }
141 
RealizeImages()142 void pgaFactory::RealizeImages()
143 {
144 	if (!imageList && deferredImagesArray)
145 	{
146 		imageList = new wxImageList(16, 16, true, deferredImagesArray->GetCount());
147 		size_t i;
148 		for (i = 0 ; i < deferredImagesArray->GetCount() ; i++)
149 		{
150 			wxImage *img = (wxImage *)deferredImagesArray->Item(i);
151 			wxBitmap bmp(*img);
152 			wxIcon *ico = new wxIcon();
153 			ico->CopyFromBitmap(bmp);
154 			imageList->Add(*ico);
155 		}
156 
157 		delete deferredImagesArray;
158 		deferredImagesArray = 0;
159 	}
160 }
161 
RegisterMenu(wxWindow * w,wxObjectEventFunction func)162 void pgaFactory::RegisterMenu(wxWindow *w, wxObjectEventFunction func)
163 {
164 	w->Connect(GetFactory(FACTORY_OFFSET)->GetId() + MNU_NEW,
165 	           GetFactory(factoryArray->GetCount() + FACTORY_OFFSET - 1)->GetId() + MNU_NEW,
166 	           wxEVT_COMMAND_MENU_SELECTED, func);
167 }
168 
169 
AppendMenu(wxMenu * menu)170 void pgaFactory::AppendMenu(wxMenu *menu)
171 {
172 	if (menu && GetNewString())
173 	{
174 		wxMenuItem *item = menu->Append(MNU_NEW + GetId(), wxGetTranslation(GetNewString()), wxGetTranslation(GetNewLongString()));
175 		if (image.IsOk())
176 		{
177 			(void)item;
178 			// doesn't work?
179 			// item->SetBitmap(wxBitmap(image));
180 		}
181 	}
182 }
183 
184 
GetMetaType()185 int pgaFactory::GetMetaType()
186 {
187 	if (IsCollection())
188 		return ((pgaCollectionFactory *)this)->GetItemFactory()->GetMetaType();
189 	return metaType;
190 }
191 
192 
pgaCollectionFactory(pgaFactory * f,const wxChar * tn,wxImage * img,wxImage * imgSm)193 pgaCollectionFactory::pgaCollectionFactory(pgaFactory *f, const wxChar *tn, wxImage *img, wxImage *imgSm)
194 	: pgaFactory(tn, f->GetNewString(), f->GetNewLongString())
195 {
196 	itemFactory = f;
197 	f->collectionFactory = this;
198 	if (img && img->IsOk())
199 	{
200 		image = *img;
201 		iconId = addIcon(img);
202 		if (imgSm && imgSm->IsOk())
203 			smallIconId = addIcon(imgSm);
204 	}
205 	else
206 		iconId = f->GetIconId();
207 }
208 
209 
CreateObjects(pgCollection * obj,ctlTree * browser,const wxString & restr)210 pgObject *pgaCollectionFactory::CreateObjects(pgCollection  *obj, ctlTree *browser, const wxString &restr)
211 {
212 	if (itemFactory)
213 		return itemFactory->CreateObjects(obj, browser, restr);
214 	return 0;
215 }
216 
217 
CreateDialog(frmMain * frame,pgObject * node,pgObject * parent)218 dlgProperty *pgaCollectionFactory::CreateDialog(frmMain *frame, pgObject *node, pgObject *parent)
219 {
220 	if (itemFactory)
221 		return itemFactory->CreateDialog(frame, node, parent);
222 	return 0;
223 }
224 
225 
226 ////////////////////////////////////////////////
227 
228 
~menuFactoryList()229 menuFactoryList::~menuFactoryList()
230 {
231 	while (GetCount())
232 	{
233 		delete (menuFactory *)Item(0);
234 		RemoveAt(0);
235 	}
236 }
237 
GetFactory(int id,bool actionOnly)238 actionFactory *menuFactoryList::GetFactory(int id, bool actionOnly)
239 {
240 	id -= MNU_ACTION;
241 	if (id >= 0 && id < (int)GetCount())
242 	{
243 		actionFactory *f = (actionFactory *)Item(id);
244 		if (f->IsAction() || !actionOnly)
245 			return f;
246 	}
247 	return 0;
248 }
249 
250 
RegisterMenu(wxWindow * w,wxObjectEventFunction func)251 void menuFactoryList::RegisterMenu(wxWindow *w, wxObjectEventFunction func)
252 {
253 	w->Connect(MNU_ACTION, MNU_ACTION + GetCount() - 1,
254 	           wxEVT_COMMAND_MENU_SELECTED, func);
255 }
256 
257 
CheckMenu(pgObject * obj,wxMenuBar * menubar,ctlMenuToolbar * toolbar)258 void menuFactoryList::CheckMenu(pgObject *obj, wxMenuBar *menubar, ctlMenuToolbar *toolbar)
259 {
260 	size_t id;
261 	for (id = MNU_ACTION ; id < GetCount() + MNU_ACTION ; id++)
262 	{
263 		actionFactory *f = GetFactory(id);
264 		if (f)
265 		{
266 			bool how = f->CheckEnable(obj);
267 			if (menubar->FindItem(id))
268 				menubar->Enable(id, how);
269 			if (toolbar)
270 				toolbar->EnableTool(id, how);
271 
272 			bool chk = f->CheckChecked(obj);
273 			wxMenuItem *itm = menubar->FindItem(id);
274 			if (itm && itm->IsCheckable())
275 				menubar->Check(id, chk);
276 		}
277 	}
278 	for (id = 0 ; id < GetCount() ; id++)
279 	{
280 		actionFactory *f = (actionFactory *)Item(id);
281 		if (f->IsSubmenu())
282 			EnableSubmenu(menubar, id + MNU_ACTION);
283 	}
284 }
285 
286 
EnableSubmenu(wxMenuBar * menuBar,int id)287 void menuFactoryList::EnableSubmenu(wxMenuBar *menuBar, int id)
288 {
289 	wxMenuItem *item = menuBar->FindItem(id);
290 	if (item)
291 	{
292 		wxMenu *menu = item->GetSubMenu();
293 		wxASSERT(menu);
294 		if (!menu)
295 			return;
296 
297 		size_t position;
298 		for (position = 0 ; position < menu->GetMenuItemCount() ; position++)
299 		{
300 			item = menu->FindItemByPosition(position);
301 			if (item && item->IsEnabled())
302 			{
303 				menuBar->Enable(id, true);
304 				return;
305 			}
306 		}
307 
308 		menuBar->Enable(id, false);
309 	}
310 }
311 
312 
AppendEnabledMenus(wxMenuBar * menuBar,wxMenu * treeContextMenu)313 void menuFactoryList::AppendEnabledMenus(wxMenuBar *menuBar, wxMenu *treeContextMenu)
314 {
315 	size_t id;
316 	wxMenuItem *lastItem = 0;
317 	for (id = MNU_ACTION ; id < GetCount() + MNU_ACTION ; id++)
318 	{
319 		actionFactory *f = GetFactory(id, false);
320 		if (f->IsAction())
321 		{
322 			if (f->GetContext())
323 			{
324 				wxMenuItem *menuItem = menuBar->FindItem(id);
325 				if (menuItem && menuItem->IsEnabled())
326 				{
327 					if (!menuItem->IsSubMenu())
328 					{
329 #if wxCHECK_VERSION(2, 9, 0)
330 						wxString lab = menuItem->GetItemLabelText();
331 #else
332 						wxString lab = menuItem->GetLabel(); // deprecated
333 #endif
334 						lastItem = treeContextMenu->Append(id, lab, menuItem->GetHelp(), menuItem->IsCheckable() ? wxITEM_CHECK : wxITEM_NORMAL);
335 						if (menuItem->IsCheckable() && menuItem->IsChecked())
336 							treeContextMenu->FindItem(id)->Check();
337 					}
338 					else
339 					{
340 						/* Copy of submenu */
341 						wxMenu *oldSubMenu = menuItem->GetSubMenu();
342 						wxMenu *newSubMenu = new wxMenu();
343 
344 						size_t i;
345 						int itemCount = 0;
346 						wxMenuItem *singleMenuItem = 0;
347 						for (i = 0; i < oldSubMenu->GetMenuItemCount(); i++)
348 						{
349 							wxMenuItem *oldMenuItem = oldSubMenu->FindItemByPosition(i);
350 							if (oldMenuItem->IsEnabled())
351 							{
352 #if wxCHECK_VERSION(2, 9, 0)
353 								wxString oldLab = oldMenuItem->GetItemLabelText();
354 #else
355 								wxString oldLab = oldMenuItem->GetLabel(); // deprecated
356 #endif
357 								newSubMenu->Append(oldMenuItem->GetId(), oldLab, oldMenuItem->GetHelp(), menuItem->IsCheckable() ? wxITEM_CHECK : wxITEM_NORMAL);
358 								if (oldMenuItem->IsCheckable() && oldMenuItem->IsChecked())
359 									newSubMenu->FindItem(oldMenuItem->GetId())->Check();
360 
361 								itemCount++;
362 								singleMenuItem = oldMenuItem;
363 							}
364 						}
365 						if (itemCount > 1)
366 						{
367 #if wxCHECK_VERSION(2, 9, 0)
368 							wxString lab = menuItem->GetItemLabelText();
369 #else
370 							wxString lab = menuItem->GetLabel(); // deprecated
371 #endif
372 							lastItem = treeContextMenu->Append(id, lab, newSubMenu);
373 						}
374 						else
375 						{
376 							delete newSubMenu;
377 							if (itemCount)
378 							{
379 #if wxCHECK_VERSION(2, 9, 0)
380 								wxString lab = singleMenuItem->GetItemLabelText();
381 #else
382 								wxString lab = singleMenuItem->GetLabel(); // deprecated
383 #endif
384 								lastItem = treeContextMenu->Append(singleMenuItem->GetId(), lab, singleMenuItem->GetHelp(), menuItem->IsCheckable() ? wxITEM_CHECK : wxITEM_NORMAL);
385 								if (singleMenuItem->IsCheckable() && singleMenuItem->IsChecked())
386 									treeContextMenu->FindItem(singleMenuItem->GetId())->Check();
387 							}
388 						}
389 					}
390 				}
391 			}
392 		}
393 		else
394 		{
395 			if (lastItem && lastItem->GetId() >= 0)
396 				lastItem = treeContextMenu->AppendSeparator();
397 		}
398 	}
399 
400 	if (lastItem && lastItem->GetId() < 0)
401 	{
402 		treeContextMenu->Remove(lastItem);
403 		delete lastItem;
404 	}
405 }
406 
407 
menuFactory(menuFactoryList * list)408 menuFactory::menuFactory(menuFactoryList *list)
409 {
410 	if (list)
411 		list->Add(this);
412 }
413 
~menuFactory()414 menuFactory::~menuFactory()
415 {
416 }
417 
actionFactory(menuFactoryList * list)418 actionFactory::actionFactory(menuFactoryList *list) : menuFactory(list)
419 {
420 	if (list)
421 		id = list->GetCount() + MNU_ACTION - 1;
422 	else
423 		id = 0;
424 	context = false;
425 }
426 
427 
428 
429