File: gui_PogChooser.py

package info (click to toggle)
fontypython 0.4.6-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 1,152 kB
  • ctags: 559
  • sloc: python: 3,619; makefile: 10
file content (274 lines) | stat: -rw-r--r-- 9,135 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
##	Fonty Python Copyright (C) 2006, 2007, 2008, 2009 Donn.C.Ingle
##	Contact: donn.ingle@gmail.com - I hope this email lasts.
##
##	This file is part of Fonty Python.
##	Fonty Python is free software: you can redistribute it and/or modify
##	it under the terms of the GNU General Public License as published by
##	the Free Software Foundation, either version 3 of the License, or
##	(at your option) any later version.
##
##	Fonty Python is distributed in the hope that it will be useful,
##	but WITHOUT ANY WARRANTY; without even the implied warranty of
##	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##	GNU General Public License for more details.
##
##	You should have received a copy of the GNU General Public License
##	along with Fonty Python.  If not, see <http://www.gnu.org/licenses/>.

import wx, locale

## June 25th 2016
## Remarking these two lines because they are causing a segfault:
##  ../src/common/stdpbase.cpp(62): assert "traits" failed in Get(): 
##  create wxApp before calling this
##  Segmentation fault (core dumped)
##
##  I do not know how to test or fix this, hence simply removing it.
##  AFAICT, stock buttons will be in the system language.
##
## Setup wxPython to access translations : enables the stock buttons.
##langid = wx.LANGUAGE_DEFAULT # Picks this up from $LANG
##mylocale = wx.Locale( langid )

from pubsub import *
from wxgui import ps

import fpsys # Global objects
import fontcontrol
import fontybugs


class PogChooser(wx.ListCtrl) :
	"""
	Basic list control for pogs - instanced by TargetPogChooser and NoteBook
	This single class (being used twice) causes terrible conceptual hardships
	and forces all kinds of twisty tests. I'm sorry for this, we need a better
	solution.
	"""
	## CLASS LEVEL variables - special things these.
	__poglistCopy = {} # To help in sorting.
	__TARGET = None
	__VIEW = None
	
	def __init__(self, parent, whoami, select = None) :
		self.indexselected = 0
		self.lastindexselected = -1
		self.parent = parent
		self.whoami = whoami

		## Use Class-level attributes to record the history of 
		## the instantiation of this class. These vars do not
		## belong to the instances, but to this one class.
		## We keep refs to the two parents of this class.
		if whoami == "SOURCEPOG" :#isinstance( self.parent, wx.Panel ):
			PogChooser.__VIEW = self
			style = wx.LC_LIST | wx.LC_AUTOARRANGE | wx.LC_SORT_ASCENDING | wx.LC_SINGLE_SEL
		else:
			PogChooser.__TARGET = self.parent
			style = wx.LC_LIST | wx.LC_AUTOARRANGE | wx.LC_SORT_ASCENDING

		il = wx.ImageList(16,16,True) 
		png = wx.Bitmap(fpsys.mythingsdir + "/pog16x16.png",wx.BITMAP_TYPE_PNG) 
		il.Add(png) 
		png = wx.Bitmap(fpsys.mythingsdir + "/pog16x16.installed.png",wx.BITMAP_TYPE_PNG) 
		il.Add(png)
		## Dec 2007 : target icon
		png = wx.Bitmap( fpsys.mythingsdir + "/pog16x16.target.png", wx.BITMAP_TYPE_PNG )
		il.Add( png )
		
		wx.ListCtrl.__init__( self,parent,-1, style=style | wx.SUNKEN_BORDER ) 
		
		self.AssignImageList(il, wx.IMAGE_LIST_SMALL) 

		self.__PC = fpsys.iPC # reuse the global pathcontrol object
		
		self.fillPogList() 
		
		## Highlight the pog selected (the last one, or the cli chosen one)
		if select:
			i = self.FindItem(-1, select)
			self.indexselected = i # Set this to help initial icon settings.
			self.Select(i, True)
		elif self.__poglistCopy:
			self.Select(0, False)
			self.indexselected = -1


		self.ClearBackground() 
		self.items = None
		
		self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.onSelect) 
		
		## This one is a double click event
		## self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.__onActivate )
		
		#self.SetCursor(wx.StockCursor(wx.CURSOR_HAND))
		
		## This subscribe line here will register TWICE since this PogChooser object is instanced
		## twice by the app...
		ps.sub(change_pog_icon, self.ChangeIcon) ##DND: class PogChooser
		
	def Sorter(self, key1, key2):
		"""
		Fetch the strings from our CLASS LEVEL copy of the pognames
		so that we can compare them via locale.
		"""
		s1,s2 = PogChooser.__poglistCopy[key1], PogChooser.__poglistCopy[key2]
		## Since the gui is unicode, I *think* I don't have to worry about errors here.
		return locale.strcoll( s1, s2 )
		
	def onSelect(self, e):
		wx.BeginBusyCursor()
		self.indexselected = e.m_itemIndex
		pognochange = False
		if self.indexselected == self.lastindexselected:
			## We have clicked on the same Pog as last time - ergo do nothing.
			pognochange = True
		self.lastindexselected = self.indexselected # Record this for next time around

		textpogname = self.GetItemText(self.indexselected) # Gets UNICODE !!!

		if self.whoami=="SOURCEPOG":
			ps.pub(source_pog_has_been_selected, textpogname, pognochange)
		else:
			ps.pub(target_pog_has_been_selected, textpogname, pognochange)
		
		self.SortOutTheDamnImages( pognochange )
				
		wx.EndBusyCursor()
		
	def SortOutTheDamnImages( self, pognochange ):
		"""
		Dec 2007 : This took me an entire day to figure out. Man...
		Determines the images of the list items.
		Is called from TargetPogChooser as well (when clear button is clicked)
		"""
		if pognochange is ():
			pognochange = True
			
		c = self.GetItemCount()
		sel = self.indexselected # the actual selection index, does not go to -1
		
		## Which kind of a McList am I?
		iAmTargetList = self.whoami=="TARGETPOG" #isinstance( self.parent, TargetPogChooser )
		## If there is an active selection?
		if sel > -1:
			for x in xrange(0, c):
				i = self.GetItem(x, 0)
				## Must make a tmp Pog before I can test installed status.
				tmpPog = fontcontrol.Pog(i.GetText())
				if tmpPog.isInstalled():
					self.SetItemImage(x, 1)
				else:
					## Handle the other icons (in the target list only)
					## that are not installed.
					if iAmTargetList:
						if x == sel:
							## No change means it *was* selected
							## and now it's been selected again
							## thus it can't be the target anymore.
							if pognochange: n = 0
							else: n = 2
							self.SetItemImage(x, n ) # new target icon
						else:
							self.SetItemImage(x, 0)
		## Tell the VIEW to imitate this picture.
			for x in xrange(0,c):
				ti = self.__TARGET.pogTargetlist.GetItem(x, 0) # the 0 is 'column'. Ignore.
				CLONE = ti.GetImage()# gets the image index, not an image bitmap.
				self.__VIEW.SetItemImage(x, CLONE)
				
	def __del__(self) :
		del self.items

	def fillPogList(self):
		"""
		This is among the very FIRST things we do.
		Fill the list with pogs.
		This will CULL any bad pogs (i.e. those with malformed content)
		Thus the PogInvalid error should not happen any more after a run.
		"""
		pl = self.__PC.getPogNames() # pl will always be a BYTE STRING list
		
		for p in pl: # 'p' is a byte string.
			ipog = fontcontrol.Pog(p)
			try: #catch pogs that are not properly formed
				if ipog.isInstalled(): i = 1 # isInstalled opens the pog file.
				else: i = 0
			except fontybugs.PogInvalid, eInst:
				## An "invalid" pog is one that does not have
				## installed/not installed on the first line.
				print _(u"(%s) skipped. It's an invalid pog.") % [p]
				continue

			## Let's try to make a unicode of p so li.SetText(p) can display it:
			try:
				p = fpsys.LSP.to_unicode( p )
			except UnicodeDecodeError:
				## We can't convert it under this locale
				print _(u"(%s) skipped. I can't display this name under your locale.") % [p]
				continue
			## Okay, we have a valid pog name to use:
			li = wx.ListItem() 
			li.SetImage(i) 
			li.SetText(p) 

			## June 25, 2016: Something in wxPython changed and li now needs an Id>0
			li.Id = 1

			id = wx.NewId()
			PogChooser.__poglistCopy[id] = p # record the pog name
			row = self.InsertItem( li ) 
			self.SetItemData( row, id ) # associate back to __poglistCopy

		self.SortItems( self.Sorter )
		
	def AddItem(self, pogname):
		"""
		Add a pogname to myself, then sort.
		"""
		li = wx.ListItem()
		li.SetImage(0)
		li.SetText(pogname)

		#July 5th, 2016 - wxPython Id fix
		li.Id = 1

		id = wx.NewId()
		self.__poglistCopy[id] = pogname 
		row = self.InsertItem(li)
		self.SetItemData( row, id )
		self.SortItems( self.Sorter )
		
	def RemoveItem(self, pogname):
		row = self.FindItem(-1, pogname)
		id = self.GetItemData(row)
		self.DeleteItem(row)
		del( PogChooser.__poglistCopy[id] ) # cull from our private store too.

	def ClearSelection(self):
		# removes all selections, even for multi-selections
		for x in range(self.GetSelectedItemCount()):
			self.Select(self.GetFirstSelected(), False)
		self.lastindexselected = -1
		
	def ChangeIcon(self):
		"""
		Change a single Pog's icon to installed/uninstalled.
		ONLY called from InstallPog and UninstallPog.
		"""
		T = fpsys.state.targetobject
		pn = T.name
		index = self.FindItem(0, pn) 
		if T.isInstalled(): n = 1
		else: n = 0
		self.SetItemImage(index, n) ## Found in wxWidgets documentation!
		
	def ClearLastIndex(self):
		"""
		We need to reset the lastindexselected so that a click on the 
		same item as last time will register. This is used in the Notebook
		when the page changes back to page 1, we want the user to
		be able to re-click the item that was clicked last time.
		"""	
		self.lastindexselected = -1