Guest User

Untitled

a guest
May 20th, 2018
135
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 11.62 KB | None | 0 0
  1. #!/usr/bin/python
  2. import sys
  3.  
  4. if sys.platform.startswith("win"):
  5. # Fetchs gtk2 path from registry
  6. import _winreg
  7. import msvcrt
  8. try:
  9. k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "Software\\GTK\\2.0")
  10. except EnvironmentError:
  11. print "You must install the Gtk+ 2.2 Runtime Environment to run this program"
  12. while not msvcrt.kbhit():
  13. pass
  14. sys.exit(1)
  15. else:
  16. gtkdir = _winreg.QueryValueEx(k, "Path")
  17. import os
  18. # we must make sure the gtk2 path is the first thing in the path
  19. # otherwise, we can get errors if the system finds other libs with
  20. # the same name in the path...
  21. os.environ['PATH'] = "%s/lib;%s/bin;" % (gtkdir[0], gtkdir[0]) + os.environ['PATH']
  22.  
  23. import pygtk
  24. pygtk.require ('2.0')
  25. import gtk
  26.  
  27. import threading
  28. import array
  29. import string
  30.  
  31. # ------------- ADT part -----------------
  32.  
  33. class Fifo:
  34. def __init__(self):
  35. self.__data = array.array('l')
  36.  
  37. def peek(self):
  38. return self.__data[-1]
  39.  
  40. def empty(self):
  41. return len(self.__data) == 0
  42.  
  43. def push(self, item):
  44. self.__data.insert(0, item)
  45.  
  46. def pop(self):
  47. return self.__data.pop()
  48.  
  49. def clear(self):
  50. while len(self.__data) != 0:
  51. self.__data.pop()
  52.  
  53. class Stack:
  54. def __init__(self):
  55. self.__data = array.array('l')
  56.  
  57. def peek(self):
  58. return self.__data[-1]
  59.  
  60. def empty(self):
  61. return len(self.__data) == 0
  62.  
  63. def push(self, item):
  64. self.__data.append(item)
  65.  
  66. def pop(self):
  67. return self.__data.pop()
  68.  
  69. def clear(self):
  70. while len(self.__data) != 0:
  71. self.__data.pop()
  72.  
  73. # ------------- Icon View part -----------------
  74.  
  75. class IconView(gtk.HBox):
  76. def __init__(self):
  77. gtk.HBox.__init__(self, gtk.FALSE, 0)
  78. self.__area = gtk.DrawingArea()
  79. self.pack_start(self.__area, gtk.TRUE, gtk.TRUE, 0)
  80. self.__area.show()
  81.  
  82. self.__scrollbar = gtk.VScrollbar(adjustment=None)
  83. self.pack_start(self.__scrollbar, gtk.FALSE, gtk.FALSE, 0)
  84. self.__scrollbar.show()
  85.  
  86. self.__selected = None # nothing selected
  87.  
  88. self.__items = 0 # number of items
  89. self.__current_row = 0
  90. self.__rows = 1 # number of rows
  91. self.__cols = 1 # number of columns
  92. self.__item_width = 1 # item width
  93. self.__item_height = 1 # item height
  94. self.__item_border = 0
  95. self.__show_labels = True
  96.  
  97. # threading
  98. self.__icon_thread_flag = True # when this becomes false, the threads ends
  99. self.__icon_lock = threading.Lock()
  100. self.__icon_event = threading.Event()
  101. self.__icon_event.clear()
  102. self.__icon_queue = Fifo()
  103. self.__icon_thread = threading.Thread(None,
  104. self.icon_thread,
  105. 'label',
  106. (self.__icon_queue,
  107. self.__icon_event,
  108. self.__icon_lock,
  109. self.get_icon,
  110. self.display_icon))
  111. self.__icon_thread.start()
  112.  
  113. self.__adjustment = self.__scrollbar.get_adjustment()
  114. self.__adjustment.set_all(0,0,0,0,0,0)
  115. self.__adjustment.connect("value_changed", self.on_scroll)
  116.  
  117. self.__area.connect("configure_event", self.on_configure)
  118. self.__area.connect("expose-event", self.on_expose)
  119. self.__area.connect("unrealize", self.on_unrealize)
  120.  
  121. def on_scroll(self, adj):
  122. current_row = int(adj.value)
  123. if current_row != self.__current_row:
  124. self.__area.queue_draw()
  125.  
  126. def on_unrealize(self, area, data = None):
  127. self.__icon_thread_flag = False
  128. self.__icon_event.set() # make sure the thread is not blocked
  129. return gtk.FALSE
  130.  
  131. def icon_thread(self, queue, event, lock, get_item, display_item):
  132. while self.__icon_thread_flag:
  133. if lock.acquire(False):
  134. while queue.empty():
  135. lock.release()
  136. event.wait()
  137. if not self.__icon_thread_flag:
  138. return
  139. lock.acquire()
  140. event.clear()
  141. index = queue.peek()
  142. lock.release()
  143. (item, width, height) = get_item(index,
  144. self.__item_width - 2 * self.__item_border,
  145. self.__item_height - 4 * self.__item_border)
  146. if lock.acquire(False):
  147. if not queue.empty():
  148. if index == queue.peek():
  149. display_item(index, item, width, height)
  150. queue.pop()
  151. lock.release()
  152.  
  153. def get_label(self, index):
  154. return ('Item %d' % index)
  155.  
  156. def set_layout_label(self, layout, label, max_width):
  157. layout.set_text(label)
  158. width, height = layout.get_pixel_size()
  159. i = -3
  160. while width > max_width:
  161. label0 = label[:i] + '...'
  162. layout.set_text(label0)
  163. width, height = layout.get_pixel_size()
  164. i -= 1
  165. return (layout, width, height)
  166.  
  167. def display_label(self, index, label):
  168. (layout, width, height) = self.set_layout_label(self.__pangolayout,
  169. label,
  170. self.__item_width - 2 * self.__item_border)
  171. row = index / self.__cols - self.__current_row
  172. col = index % self.__cols
  173. x = col * self.__item_width + self.__item_border
  174. y = (row + 1) * self.__item_height - self.__item_border - height
  175. self.__window.draw_layout(self.__gc,
  176. x,
  177. y,
  178. layout)
  179.  
  180. def get_icon(self, index, width, height):
  181. b = width*3*height*['\0']
  182. for i in range(width):
  183. for j in range(height):
  184. b[3*height*i+3*j] = chr((index % 32)*4)
  185. b[3*height*i+3*j+1] = chr((index % 32)*4)
  186. b[3*height*i+3*j+2] = chr((index % 32)*4)
  187. buff = string.join(b, '')
  188. return (buff, width, height)
  189.  
  190. def display_icon(self, index, icon, width, height):
  191. row = index / self.__cols - self.__current_row
  192. col = index % self.__cols
  193. x = col * self.__item_width + self.__item_border + (width - self.__item_width) / 2
  194. y = row * self.__item_height + self.__item_border + (height - self.__item_height) / 2
  195.  
  196. gtk.threads_enter()
  197. self.__window.draw_rgb_image(self.__gc, x, y, width, height,
  198. gtk.gdk.RGB_DITHER_NONE, icon)
  199. gtk.threads_leave()
  200.  
  201. def on_expose(self, area, event):
  202. rect = event.area
  203. self.__pangolayout = area.create_pango_layout("")
  204. self.__style = area.get_style()
  205. self.__window = area.window
  206. self.__gc = self.__style.fg_gc[gtk.STATE_NORMAL]
  207.  
  208. # determin the area that needs to be drawn
  209. col1 = rect.x / self.__item_width
  210. col2 = min((rect.x + rect.width) / self.__item_width + 1, self.__cols)
  211. row1 = rect.y / self.__item_height
  212. row2 = min((rect.y + rect.height) / self.__item_height + 1, self.__rows) # we don't let row2 be more than the total number of rows
  213.  
  214. self.__icon_lock.acquire()
  215. self.__icon_queue.clear()
  216.  
  217. self.__current_row = int(self.__adjustment.value)
  218. if col1 == 0 and col2 == 0:
  219. for row in range(row1, row2):
  220. if row < self.__items: # the col is always 0
  221. index = row + self.__current_row
  222. self.__icon_queue.push(index)
  223. # labels
  224. label = self.get_label(index)
  225. self.display_label(index, label)
  226. else:
  227. for row in range(row1, row2):
  228. for col in range(col1, col2):
  229. index = (row + self.__current_row) * self.__cols + col
  230. if index < self.__items:
  231. self.__icon_queue.push(index)
  232. # labels
  233. label = self.get_label(index)
  234. self.display_label(index, label)
  235.  
  236. self.__icon_lock.release()
  237. self.__icon_event.set()
  238.  
  239. return gtk.TRUE
  240.  
  241. def on_configure(self, widget, event, data=None):
  242. width = event.width
  243. height = event.height
  244. self.__cols = width / self.__item_width
  245. if self.__cols <= 0:
  246. self.__cols = 1 # we can't have less than 1 column !
  247. self.__rows = self.__items / self.__cols
  248. while self.__rows * self.__cols < self.__items:
  249. self.__rows += 1
  250.  
  251. page_size = int(height / self.__item_height)
  252. if page_size < 1:
  253. page_size = 1
  254. if page_size > self.__rows:
  255. page_size = self._rows
  256. self.__adjustment.set_all(0, 0, self.__rows, 1, page_size, page_size)
  257. return gtk.FALSE
  258.  
  259. def set_all(self, items, width, height, border, show_labels = True):
  260. # set all properties of the icon view with one call
  261. # items - number of items fromthe view
  262. # width - width of one item
  263. # height - height of one item
  264. # border - the border arround the image / text
  265. # show_labels - if true, print some labels under the item
  266. if items < 0:
  267. items = 0
  268. if width < 1:
  269. width = 1
  270. if height < 1:
  271. height = 1
  272. if border < 0:
  273. border = 0
  274.  
  275. self.__items = items
  276. self.__item_width = width
  277. self.__item_height = height
  278. self.__item_border = border
  279. self.__show_labels = show_labels
  280.  
  281. # redraw all items now ...
  282.  
  283. def get_selected(self):
  284. return self.__selected
  285.  
  286. def set_selected(self, value):
  287. self.__selected = value
  288.  
  289. def get_rows(self):
  290. return self.__rows
  291.  
  292. def get_cols(self):
  293. return self.__cols
  294.  
  295. selected = property(get_selected, set_selected, None, 'selected item')
  296. rows = property(get_rows, None, None, 'number of rows')
  297. cols = property(get_cols, None, None, 'number of rows')
  298.  
  299. # ------------- Test part -----------------
  300.  
  301. class Test:
  302. def __init__(self):
  303. self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
  304.  
  305. # You should always remember to connect the delete_event signal
  306. # to the main window. This is very important for proper intuitive
  307. # behavior
  308. self.window.connect("delete_event", self.delete_event)
  309.  
  310. # Create an icon-view and adds it to the window
  311. icon_view = IconView()
  312. icon_view.set_all(300, 69, 128, 5)
  313. icon_view.set_size_request(400, 300) # make the icon view a bit bigger
  314. self.window.add(icon_view)
  315. icon_view.show()
  316.  
  317. # the last thing we do is showing the window
  318. self.window.show()
  319.  
  320. def main(self):
  321. gtk.main()
  322.  
  323. def delete_event(self, widget, event, data=None):
  324. self.window.hide()
  325. gtk.main_quit()
  326. return gtk.FALSE
  327.  
  328. if __name__ == "__main__":
  329. gtk.threads_init()
  330. gtk.threads_enter()
  331. test = Test()
  332. test.main()
  333. gtk.threads_leave()
Add Comment
Please, Sign In to add comment