Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- import sys
- if sys.platform.startswith("win"):
- # Fetchs gtk2 path from registry
- import _winreg
- import msvcrt
- try:
- k = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, "Software\\GTK\\2.0")
- except EnvironmentError:
- print "You must install the Gtk+ 2.2 Runtime Environment to run this program"
- while not msvcrt.kbhit():
- pass
- sys.exit(1)
- else:
- gtkdir = _winreg.QueryValueEx(k, "Path")
- import os
- # we must make sure the gtk2 path is the first thing in the path
- # otherwise, we can get errors if the system finds other libs with
- # the same name in the path...
- os.environ['PATH'] = "%s/lib;%s/bin;" % (gtkdir[0], gtkdir[0]) + os.environ['PATH']
- import pygtk
- pygtk.require ('2.0')
- import gtk
- import threading
- import array
- import string
- # ------------- ADT part -----------------
- class Fifo:
- def __init__(self):
- self.__data = array.array('l')
- def peek(self):
- return self.__data[-1]
- def empty(self):
- return len(self.__data) == 0
- def push(self, item):
- self.__data.insert(0, item)
- def pop(self):
- return self.__data.pop()
- def clear(self):
- while len(self.__data) != 0:
- self.__data.pop()
- class Stack:
- def __init__(self):
- self.__data = array.array('l')
- def peek(self):
- return self.__data[-1]
- def empty(self):
- return len(self.__data) == 0
- def push(self, item):
- self.__data.append(item)
- def pop(self):
- return self.__data.pop()
- def clear(self):
- while len(self.__data) != 0:
- self.__data.pop()
- # ------------- Icon View part -----------------
- class IconView(gtk.HBox):
- def __init__(self):
- gtk.HBox.__init__(self, gtk.FALSE, 0)
- self.__area = gtk.DrawingArea()
- self.pack_start(self.__area, gtk.TRUE, gtk.TRUE, 0)
- self.__area.show()
- self.__scrollbar = gtk.VScrollbar(adjustment=None)
- self.pack_start(self.__scrollbar, gtk.FALSE, gtk.FALSE, 0)
- self.__scrollbar.show()
- self.__selected = None # nothing selected
- self.__items = 0 # number of items
- self.__current_row = 0
- self.__rows = 1 # number of rows
- self.__cols = 1 # number of columns
- self.__item_width = 1 # item width
- self.__item_height = 1 # item height
- self.__item_border = 0
- self.__show_labels = True
- # threading
- self.__icon_thread_flag = True # when this becomes false, the threads ends
- self.__icon_lock = threading.Lock()
- self.__icon_event = threading.Event()
- self.__icon_event.clear()
- self.__icon_queue = Fifo()
- self.__icon_thread = threading.Thread(None,
- self.icon_thread,
- 'label',
- (self.__icon_queue,
- self.__icon_event,
- self.__icon_lock,
- self.get_icon,
- self.display_icon))
- self.__icon_thread.start()
- self.__adjustment = self.__scrollbar.get_adjustment()
- self.__adjustment.set_all(0,0,0,0,0,0)
- self.__adjustment.connect("value_changed", self.on_scroll)
- self.__area.connect("configure_event", self.on_configure)
- self.__area.connect("expose-event", self.on_expose)
- self.__area.connect("unrealize", self.on_unrealize)
- def on_scroll(self, adj):
- current_row = int(adj.value)
- if current_row != self.__current_row:
- self.__area.queue_draw()
- def on_unrealize(self, area, data = None):
- self.__icon_thread_flag = False
- self.__icon_event.set() # make sure the thread is not blocked
- return gtk.FALSE
- def icon_thread(self, queue, event, lock, get_item, display_item):
- while self.__icon_thread_flag:
- if lock.acquire(False):
- while queue.empty():
- lock.release()
- event.wait()
- if not self.__icon_thread_flag:
- return
- lock.acquire()
- event.clear()
- index = queue.peek()
- lock.release()
- (item, width, height) = get_item(index,
- self.__item_width - 2 * self.__item_border,
- self.__item_height - 4 * self.__item_border)
- if lock.acquire(False):
- if not queue.empty():
- if index == queue.peek():
- display_item(index, item, width, height)
- queue.pop()
- lock.release()
- def get_label(self, index):
- return ('Item %d' % index)
- def set_layout_label(self, layout, label, max_width):
- layout.set_text(label)
- width, height = layout.get_pixel_size()
- i = -3
- while width > max_width:
- label0 = label[:i] + '...'
- layout.set_text(label0)
- width, height = layout.get_pixel_size()
- i -= 1
- return (layout, width, height)
- def display_label(self, index, label):
- (layout, width, height) = self.set_layout_label(self.__pangolayout,
- label,
- self.__item_width - 2 * self.__item_border)
- row = index / self.__cols - self.__current_row
- col = index % self.__cols
- x = col * self.__item_width + self.__item_border
- y = (row + 1) * self.__item_height - self.__item_border - height
- self.__window.draw_layout(self.__gc,
- x,
- y,
- layout)
- def get_icon(self, index, width, height):
- b = width*3*height*['\0']
- for i in range(width):
- for j in range(height):
- b[3*height*i+3*j] = chr((index % 32)*4)
- b[3*height*i+3*j+1] = chr((index % 32)*4)
- b[3*height*i+3*j+2] = chr((index % 32)*4)
- buff = string.join(b, '')
- return (buff, width, height)
- def display_icon(self, index, icon, width, height):
- row = index / self.__cols - self.__current_row
- col = index % self.__cols
- x = col * self.__item_width + self.__item_border + (width - self.__item_width) / 2
- y = row * self.__item_height + self.__item_border + (height - self.__item_height) / 2
- gtk.threads_enter()
- self.__window.draw_rgb_image(self.__gc, x, y, width, height,
- gtk.gdk.RGB_DITHER_NONE, icon)
- gtk.threads_leave()
- def on_expose(self, area, event):
- rect = event.area
- self.__pangolayout = area.create_pango_layout("")
- self.__style = area.get_style()
- self.__window = area.window
- self.__gc = self.__style.fg_gc[gtk.STATE_NORMAL]
- # determin the area that needs to be drawn
- col1 = rect.x / self.__item_width
- col2 = min((rect.x + rect.width) / self.__item_width + 1, self.__cols)
- row1 = rect.y / self.__item_height
- 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
- self.__icon_lock.acquire()
- self.__icon_queue.clear()
- self.__current_row = int(self.__adjustment.value)
- if col1 == 0 and col2 == 0:
- for row in range(row1, row2):
- if row < self.__items: # the col is always 0
- index = row + self.__current_row
- self.__icon_queue.push(index)
- # labels
- label = self.get_label(index)
- self.display_label(index, label)
- else:
- for row in range(row1, row2):
- for col in range(col1, col2):
- index = (row + self.__current_row) * self.__cols + col
- if index < self.__items:
- self.__icon_queue.push(index)
- # labels
- label = self.get_label(index)
- self.display_label(index, label)
- self.__icon_lock.release()
- self.__icon_event.set()
- return gtk.TRUE
- def on_configure(self, widget, event, data=None):
- width = event.width
- height = event.height
- self.__cols = width / self.__item_width
- if self.__cols <= 0:
- self.__cols = 1 # we can't have less than 1 column !
- self.__rows = self.__items / self.__cols
- while self.__rows * self.__cols < self.__items:
- self.__rows += 1
- page_size = int(height / self.__item_height)
- if page_size < 1:
- page_size = 1
- if page_size > self.__rows:
- page_size = self._rows
- self.__adjustment.set_all(0, 0, self.__rows, 1, page_size, page_size)
- return gtk.FALSE
- def set_all(self, items, width, height, border, show_labels = True):
- # set all properties of the icon view with one call
- # items - number of items fromthe view
- # width - width of one item
- # height - height of one item
- # border - the border arround the image / text
- # show_labels - if true, print some labels under the item
- if items < 0:
- items = 0
- if width < 1:
- width = 1
- if height < 1:
- height = 1
- if border < 0:
- border = 0
- self.__items = items
- self.__item_width = width
- self.__item_height = height
- self.__item_border = border
- self.__show_labels = show_labels
- # redraw all items now ...
- def get_selected(self):
- return self.__selected
- def set_selected(self, value):
- self.__selected = value
- def get_rows(self):
- return self.__rows
- def get_cols(self):
- return self.__cols
- selected = property(get_selected, set_selected, None, 'selected item')
- rows = property(get_rows, None, None, 'number of rows')
- cols = property(get_cols, None, None, 'number of rows')
- # ------------- Test part -----------------
- class Test:
- def __init__(self):
- self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
- # You should always remember to connect the delete_event signal
- # to the main window. This is very important for proper intuitive
- # behavior
- self.window.connect("delete_event", self.delete_event)
- # Create an icon-view and adds it to the window
- icon_view = IconView()
- icon_view.set_all(300, 69, 128, 5)
- icon_view.set_size_request(400, 300) # make the icon view a bit bigger
- self.window.add(icon_view)
- icon_view.show()
- # the last thing we do is showing the window
- self.window.show()
- def main(self):
- gtk.main()
- def delete_event(self, widget, event, data=None):
- self.window.hide()
- gtk.main_quit()
- return gtk.FALSE
- if __name__ == "__main__":
- gtk.threads_init()
- gtk.threads_enter()
- test = Test()
- test.main()
- gtk.threads_leave()
Add Comment
Please, Sign In to add comment