# vim: noet
import cStringIO, os, sys, thread, time
from Tkinter import *
import Image
import string
DEBUG = False
EMULATE_CONTROLLER = True # This can be set to false once I bind keyboard input to controller signals.
PARENT = None
Emulating = True
UniqueID = 0
def lock():
pass
def unlock():
pass
def now():
import time
return time.ctime()[:-8]
class Window( object ):
def __init__(self):
global PARENT, EMULATE_CONTROLLER
if not PARENT:
self.root = Tk()
else:
self.root = Toplevel(PARENT.root)
self.frame = Frame(self.root)
self.frame.pack(side = TOP, expand = YES, fill = BOTH)
#self.canvas = Canvas(self.frame, width = 720, height = 480, bg = "black")
self.canvas = Canvas(self.frame, width = 1280, height = 720, bg = "black")
self.canvas.pack(fill = BOTH)
if EMULATE_CONTROLLER:
self.controllerPanel = Frame(self.frame)
self.controllerPanel.pack(fill = BOTH, expand = YES)
self.makeController(self.controllerPanel)
if not PARENT: PARENT = self
self.controls = {}
self.activeControl = None
def makeController(self, panel):
bg = Canvas(panel, height = 190)
bg.pack(side = LEFT)
self.ctrlpic = PhotoImage(file = sys.prefix + "/lib/controller.gif")
bg.create_image(0, 0, image = self.ctrlpic, anchor = NW)
buttons = [ ('Left ', self.ACTION_MOVE_LEFT, 100, 100),
('Right', self.ACTION_MOVE_RIGHT, 150, 100),
(' Up ', self.ACTION_MOVE_UP, 125, 70),
('Down', self.ACTION_MOVE_DOWN, 125, 130),
('X', self.ACTION_UNKNOWN, 210, 50), #?
('Y', self.ACTION_DISPLAY, 245, 35),
('A', self.ACTION_SELECT, 225, 90),
('B', self.ACTION_BACK, 265, 70),
('White', self.ACTION_CONTEXT_MENU, 210, 130),
('Black', self.ACTION_UNKNOWN, 270, 110), #?
(' Back', self.ACTION_MENU, 5, 90),
('Start', self.ACTION_STOP, 5, 120),
('L. Trigger', self.ACTION_SKIP_NEXT, 5, 5),
('R. Trigger', self.ACTION_SKIP_PREVIOUS, 290, 5)]
for item in buttons:
btn = Button(bg, text = item[0], command = item[1])
btn.pack()
bg.create_window(item[2], item[3], window = btn, anchor = NW)
def ACTION_MOVE_LEFT(self):
self.onAction(1)
self.setFocus(self.activeControl.toleft)
def ACTION_MOVE_RIGHT(self):
self.onAction(2)
self.setFocus(self.activeControl.toright)
def ACTION_MOVE_UP(self):
if self.activeControl.type == "List":
lbox = self.activeControl
pos = self.activeControl.getSelectedPosition()
if pos == 0:
pos = lbox.tkList.size() - 1
#self.setFocus(self.activeControl.above)
else:
pos -= 1
lbox.tkList.see(pos)
lbox.tkList.selection_clear(0, lbox.tkList.size())
lbox.tkList.selection_set(pos)
else:
self.setFocus(self.activeControl.above)
self.onAction(3)
def ACTION_MOVE_DOWN(self):
if self.activeControl.type == "List":
lbox = self.activeControl
pos = lbox.getSelectedPosition()
if pos == lbox.tkList.size() - 1:
pos = 0
#self.setFocus(self.activeControl.below)
else:
pos += 1
lbox.tkList.see(pos)
lbox.tkList.selection_clear(0, lbox.tkList.size())
lbox.tkList.selection_set(pos)
else:
self.setFocus(self.activeControl.below)
self.onAction(4)
def ACTION_SKIP_NEXT(self): self.onAction(5)
def ACTION_SKIP_PREVIOUS(self): self.onAction(6)
def ACTION_SELECT(self):
self.onAction(7)
self.onControl(self.activeControl)
def ACTION_DISPLAY(self): self.onAction(18)
def ACTION_BACK(self): self.onAction(9)
def ACTION_MENU(self): self.onAction(10)
def ACTION_STOP(self): self.onAction(13)
def ACTION_CONTEXT_MENU(self): self.onAction(117)
def ACTION_UNKNOWN(self): self.onAction(0)
def addControl(self, control):
self.activeControl = control
control.Create(self)
self.activeControl.tkObj.focus()
try: self.canvas.create_window(control.top, control.left, window = control.tkObj, anchor = NW)
except: pass
self.canvas.update()
def getFocus( self ):
return None
def removeControl(self, control):
try: control.Destroy(self)
except: pass
def setFocus(self, control):
self.activeControl = control
self.activeControl.tkObj.focus()
if control.type == "List":
control.tkList.see(control.getSelectedPosition())
control.tkList.selection_clear(0, control.tkList.size())
control.tkList.selection_set(control.getSelectedPosition())
control.tkList.focus_set()
def doModal(self):
self.root.mainloop()
def close(self):
if PARENT:
self.ctrlpic = None
self.root.destroy()
self.root.quit()
else:
self.ctrlpic = None
self.root.quit()
def onAction(self, action):
if action == 10: self.close()
def onControl(self, control):
pass
def getHeight(self):
#return 480
return 720
def getWidth(self):
#return 720
return 1280
def Emulating(self):
return True
class Dialog( object ):
def ok(self, title, line1, line2 = "", line3 = ""): # Show a dialog 'OK'.
import tkMessageBox
text = line1
if line2: text += "\n" + line2
if line3: text += "\n" + line3
box = tkMessageBox.showinfo(title, text)
return True
def select(self, title, li): # Show a select dialog.
import time
# time.sleep(1)
self.root = Toplevel()
self.root.title(title)
box = Frame(self.root)
box.pack(expand = YES, fill = BOTH)
ybar = Scrollbar(box)
xbar = Scrollbar(box)
lList = Listbox(box, relief = SUNKEN)
ybar.config(command = lList.yview)
xbar.config(command = lList.xview, orient = "horizontal")
lList.config(yscrollcommand = ybar.set, xscrollcommand = xbar.set)
xbar.pack(side = BOTTOM, fill = X)
ybar.pack(side = RIGHT, fill = Y)
lList.pack(side = LEFT, expand = YES, fill = BOTH)
pos = 0
for item in li:
lList.insert(pos, item)
pos = pos + 1
lList.bind("<Double-1>", self.choose)
self.choices = lList
self.choice = None
self.root.focus_set()
self.root.grab_set()
self.root.wait_window()
return self.choice
def choose(self, event):
self.choice = int(self.choices.curselection()[0])
self.root.destroy()
def yesno(self, title, line1, line2 = "", line3 = ""): # Show a dialog 'YES / NO'.
import tkMessageBox
text = line1
if line3: text += "\n" + line2
if line3: text += "\n" + line3
answer = tkMessageBox.askyesno(title, text)
return answer
class Control( object ):
def __init__(self, type, top, left, width, height):
#!!! Add bounds checking of passed variables (ints are positive ints, etc.)
self.ID = getUniqueID()
self.type = type
self.top, self.left = top, left
self.height, self.width = height, width
self.below, self.above, self.toleft, self.toright = self, self, self, self
self.tkObj = None
def Destroy( self ):
if self.tkObj:
self.tkObj.destroy()
def controlDown(self, Control): #controlDown( Control ) -- Set onDown control.
self.below = Control
def controlUp(self, Control): #controlUp( Control ) -- Set onUp control.
self.above = Control
def controlLeft(self, Control): #controlLeft( Control ) -- Set onLeft control.
self.toleft = Control
def controlRight(self, Control): # controlRight( Control ) -- Set onRight control.
self.toright = Control
def setNavigation(self, up, down, left, right): # setNavigation( Control up, Control down, Control left, Control right) -- Set's navigation.
self.below, self.above, self.toleft, self.toright = up, down, left, right
# Same as controlUp(), controlDown(), controlLeft(), controlRight().
def getId(self): # getId(...) -- Get the control's current id.
return self.ID
def setHeight(self, height): # setHeight(int height) -- Set's the height of this control.
self.height = height
def setWidth(self, width): # setWidth(int width) -- Set's the width of this control.
self.width = width
def setPosition(self, x, y): # setPosition(int x, int y) -- Set's the position of this control.
self.top, self.left = x, y
def setVisible(self, isVisible): # setVisible(bool) -- Hide's or Show's this control.
pass
# if isVisible:
# try: self.tkObj.pack()
# except: print "Failed to pack"
# else:
# try: self.tkObj.forget()
# except: print "Failed to forget"
class ControlButton(Control):
def __init__(
self,
x, y, width, height,
label = "",
focusTexture = '0xFFFFFFFF', noFocusTexture = '0xFFFFFFFF',
textXOffset = 0, textYOffset = 0, alignment = 0, font = 'font13',
textColor='0xFFFFFFFF', disabledColor='0x60ffffff'):
type = "Button"
width = int(width / 9)
height = int(height / 17)
Control.__init__(self, type, x, y, width, height)
self.text = label
def Create(self, win):
self.tkObj = Button(win.canvas, text = self.text, command = (lambda: win.onControl(self)))
self.tkObj.config(font = ('arial', 10, 'normal'), width = self.width, height = self.height)
self.tkObj.pack()
def setLabel( self, label ):
self.tkObj.config(text = label)
class ControlCheckMark(Control):
def __init__(self, x, y, width, height, label="", focusTexture="",
noFocusTexture="", checkWidth=30, checkHeight=30, alignment=0,
font="font13", textColor="0xffffffff", disabledColor="0x60ffffff" ):
type = "Button"
width = int(width / 9)
height = int(height / 17)
Control.__init__(self, type, x, y, width, height)
self.text = label
def Create(self, win):
self.tkObj = Button(win.canvas, text = self.text, command = (lambda: win.onControl(self)))
self.tkObj.config(font = ('arial', 10, 'normal'), width = self.width, height = self.height)
self.tkObj.pack()
def getSelected( self ):
return False
def setDisabledColor( self, color='0xFFFF3300' ):
pass
def setLabel( self, label ):
self.tkObj.config(text = label)
def setSelected( self, isSelected=False ):
pass
class ControlSlider(Control):
def __init__(self, x, y, w, h, bgTexture=None, midTexture=None, midTextureFocus=None, type=None, controlOffsetX=None, controlOffsetY=None ):
type = "Button"
width = int(w / 9)
height = int(h / 17)
Control.__init__(self, type, x, y, width, height)
self.text = ''
def Create(self, win):
self.tkObj = Button(win.canvas, text = self.text, command = (lambda: win.onControl(self)))
self.tkObj.config(font = ('arial', 10, 'normal'), width = self.width, height = self.height)
self.tkObj.pack()
def getPercentage( self ):
return None
def getIntValue( self ):
return None
def getFloatValue( self ):
return None
def getType( self ):
return 0
def getControlOffsetX( self ):
return 0
def getControlOffsetY( self ):
return 0
def setRange( self, start, end ):
pass
def setFloatRange( self, start, end ):
pass
def setPercentage( self, val ):
pass
def setIntValue( self, val ):
pass
def setFloatValue( self, val ):
pass
def setFloatInterval( self, val ):
pass
def setControlOffsetX( self, val ):
pass
def setControlOffsetY( self, val ):
pass
class ControlFadeLabel(Control):
def __init__(self,
top, left, width, height, fontStyle, fontColor, alignment):
type = "FadeLabel"
Control.__init__(self, type, top, left, width, height)
self.text = ""
self.scrollpoint = ""
self.fontColor = fontColor
self.changed = False
self.threadId = None
def Create(self, win):
self.tkObj = Label(win.canvas, text = self.text, justify = LEFT)#, fg = self.fontColor)
self.tkObj.pack(anchor = NW)
self.threadId = thread.start_new_thread(self.scrollOn, (self.text,))
def Destroy( self ):
self.threadId = None
Control.Destroy( self )
def addLabel(self, newLabel):
if self.text: self.text += " | " + newLabel
else: self.text = newLabel
self.changed = True
def scrollOn(self,stuff):
try:
text = ""
while self.threadId:
if self.text:
if self.changed:
self.scrollpoint = self.text
self.changed = False
else:
a, b = self.scrollpoint[0], self.scrollpoint[1:]
self.scrollpoint = b+a
self.tkObj.config(text = self.scrollpoint)
time.sleep( 0.25 )
except:
pass
def reset(self):
self.text = ""
class ControlImage(Control):
def __init__(self, top, left, width, height, filename, colorkey=None):
type = "Image"
width = int(width / 8)
height = int(height / 18)
Control.__init__(self, type, top, left, width, height)
if filename in [".GIF", ".gif"]:
self.pic = PhotoImage(file = filename)
else:
tempname = "XBMCEmulatorImageTemp.gif"
source = Image.open(filename) # For every such picture, opens it as an Image...
source.save(tempname, "GIF")
self.pic = PhotoImage(file = tempname)
os.remove(tempname)
def Create(self, win):
self.tkObj = Label(win.canvas, image = self.pic)
self.tkObj.pack()
class ControlLabel(Control):
def __init__(self,
top, left, width, height, text, fontStyle = None, fontColor = None,
disabledColor = None, alignment = None, hasPath = None):
type = "Label"
width = int(width / 8)
height = int(height / 18)
Control.__init__(self, type, top, left, width, height)
self.text = text
self.fontStyle = fontStyle
self.fontColor = fontColor
def Create(self, win):
self.tkObj = Label(win.canvas, text = self.text)
self.tkObj.config(font = ('arial', 10, 'normal'), justify = LEFT)#, width = self.width, height = self.height)
self.tkObj.pack(anchor = NW)
def setLabel(self, txt):
self.text = txt
try: self.tkObj.config(text = self.text)
except: pass
class ControlList(Control):
def __init__(self, top, left, width, height, fontName = "", fontSize = ""):
type = "List"
width = int(width / 8)
height = int(height / 18)
Control.__init__(self, type, top, left, width, height)
self.items = []
def Create(self, win):
self.parent = win
self.tkObj = Frame(win.canvas)
self.ybar = Scrollbar(self.tkObj)
self.xbar = Scrollbar(self.tkObj)
self.tkList = Listbox(self.tkObj, relief = SUNKEN)
self.ybar.config(command = self.tkList.yview)
self.xbar.config(command = self.tkList.xview, orient = "horizontal")
self.tkList.config(font = ('arial', 10, 'normal'), width = self.width, height = self.height)
self.tkList.config(yscrollcommand = self.ybar.set, xscrollcommand = self.xbar.set)
self.xbar.pack(side = BOTTOM, fill = X)
self.ybar.pack(side = RIGHT, fill = Y)
self.tkList.pack(side = LEFT, expand = YES, fill = BOTH)
def addItem(self, item):
newItem = ListItem(item)
pos = self.tkList.size()
self.tkList.insert(pos, newItem.getLabel())
self.items.append(newItem)
def getSelectedPosition(self):
try:
pos = int(self.tkList.curselection()[0])
return pos
except:
if DEBUG: print "getSelectedPosition has returned an empty list. 'I'm workin' on it!'"
return False
def getSelectedItem(self):
lookup = self.getSelectedPosition()
return self.items[lookup]
def getSpinControl(self):
if DEBUG: print "The function 'getSpinControl' has not yet been added to this emulator."
def reset(self):
self.items = []
self.tkList.delete(0, self.tkList.size())
def setImageDimensions(self, width, height):
if DEBUG: print "The function 'setImageDimensions' has not yet been added to this emulator."
def setItemHeight(self, height):
if DEBUG: print "The function 'setItemHeight' has not yet been added to this emulator."
def setSpace(self, space): # -- Set's the space between ListItems
if DEBUG: print "The function 'setSpace' has not yet been added to this emulator."
class ListItem( object ):
def __init__(self, label="", label2="", iconImage=None, thumbnailImage=None ):
self.label = label
def setLabel(self, text):
self.label = text
def setLabel2(self, text):
self.label2 = text
def getLabel(self):
return self.label
def getLabel2(self):
return self.label
def setIconImage( self, image ):
pass
def setThumbnailImage( self, image ):
pass
class ControlTextBox(Control):
def __init__(self, top, left, width, height, fontStyle, fontColor):
type = "TextBox"
width = int(width / 8)
height = int(height / 18)
Control.__init__(self, type, top, left, width, height)
self.fontStyle = fontStyle
self.fontColor = fontColor
self.text = ""
def Create(self, win):
self.tkObj = Label(win.canvas, text = self.text)
self.tkObj.config(font = ('arial', 10, 'normal'), width = self.width, height = self.height, justify = LEFT)
self.tkObj.pack()
def setText(self, txt):
self.text = txt
# if self.tkObj: self.tkObj.config(text = self.text)
def reset(self):
self.text = ""
# if self.tkObj: self.tkObj.config(text = self.text)
def getSpinControl(self):
if DEBUG: print "The function 'getSpinControl' has not yet been added to this emulator."
def getUniqueID():
global UniqueID
ID = UniqueID
UniqueID += 1
return ID
|