### /gui/ui.py

import wx
import wx.lib.ogl as ogl
from gui.imageimport import *


import filter.filter as filter
from gui import dlgView
from gui import view
from obj.objImage  import objImage
from obj.objFilter import objFilter

#------------------------------------------------------------------------------

#--- Menu IDs
FILE_NEW			= 1000
FILE_OPEN			= 1010
FILE_SAVE			= 1020
FILE_SAVEAS			= 1030
FILE_EXIT			= 1040

IMAGE_OPEN			= 2000
IMAGE_MAKE			= 2010
IMAGE_DELETE		= 2020
IMAGE_VIEW			= 2030

FILTER_ANCHOR		= 3000
FILTER_BLEND		= 3010
FILTER_COPY			= 3020
FILTER_CROP			= 3030
FILTER_DC			= 3040
FILTER_DESATURATE   = 3050
FILTER_I2G			= 3060
FILTER_MASK			= 3070
FILTER_REPLACE    	= 3080
FILTER_RESIZE		= 3090
FILTER_ROTATE		= 3100
FILTER_SCORE		= 3110
FILTER_DELETE		= 3120

CONNECT_CONNECT		= 4000
CONNECT_DISCONNECT	= 4010

OPTION_PREFERENCES  = 5000

HELP_ABOUT			= 6000

#------------------------------------------------------------------------------
class menuFile(wx.Menu):
	def __init__(self):
		wx.Menu.__init__(self)
		self.Append(FILE_NEW, "&New\tCTRL-N")
		self.Append(FILE_OPEN, "&Open\tCTRL-O")
		self.Append(FILE_SAVE, "&Save\tCTRL-S")
		self.Append(FILE_SAVEAS, "Save &As...\tSHIFT-CTRL-S")
		self.AppendSeparator()
		self.Append(FILE_EXIT, "&Exit")

class menuImage(wx.Menu):
	def __init__(self):
		wx.Menu.__init__(self)
		self.Append(IMAGE_OPEN,"&Open\tI")
		self.Append(IMAGE_MAKE,"&Make\tM")
		self.AppendSeparator()
		self.Append(IMAGE_DELETE,"&Delete\tDELETE")
		self.AppendSeparator()
		self.Append(IMAGE_VIEW,"&View\tV")
		

class menuFilter(wx.Menu):
	def __init__(self):
		wx.Menu.__init__(self)
		self.Append(FILTER_ANCHOR,"&Anchor\tA")
		self.Append(FILTER_BLEND,"&Blend\tB")
		self.Append(FILTER_COPY,"Cop&y\tY")
		self.Append(FILTER_CROP,"Cro&p\tP")
		self.Append(FILTER_DC,"Dimension Conver&t\tT")
		self.Append(FILTER_DESATURATE,"Desat&urate\tU")
		self.Append(FILTER_I2G,"Image to &Grid\tG")
		self.Append(FILTER_MASK,'Mas&k\tK')
		self.Append(FILTER_REPLACE,"Rep&lace\tL")
		self.Append(FILTER_RESIZE,"&Resize\tR")
		self.Append(FILTER_ROTATE,"Rotat&e\tE")
		self.AppendSeparator()
		self.Append(FILTER_SCORE,"&Score\tS")
		self.AppendSeparator()
		self.Append(FILTER_DELETE,"&Delete\tDELETE")
	
class menuConnect(wx.Menu):
	def __init__(self):
		wx.Menu.__init__(self)
		self.Append(CONNECT_CONNECT,"&Connect\tC")
		self.Append(CONNECT_DISCONNECT,"&Disconnect\tD")

class menuOption(wx.Menu):
	def __init__(self):
		wx.Menu.__init__(self)
		self.Append(OPTION_PREFERENCES,"&Preferences")
		
class menuHelp(wx.Menu):
	def __init__(self):
		wx.Menu.__init__(self)
		self.Append(HELP_ABOUT,"&About")

#----------------------------------------------------------

class menuBar(wx.MenuBar):
	def __init__(self):
		wx.MenuBar.__init__(self)
		self.Append(menuFile(),"&File")
		self.Append(menuImage(),"&Image")
		self.Append(menuFilter(),"Fi&lter")
		self.Append(menuConnect(),"&Connect")
		self.Append(menuOption(),"&Options")
		self.Append(menuHelp(),"&Help")

#------------------------------------------------------------------------------

class MainCanvas(ogl.ShapeCanvas):
	def __init__(self,frame):
		ogl.ShapeCanvas.__init__(self,frame)
		self.shapesize = 96
		
		self.frame = frame
		self.SetBackgroundColour('#666666')
		
		self.diagram = ogl.Diagram()
		self.SetDiagram(self.diagram)
		self.diagram.SetCanvas(self)
		
		self.images = []
		self.filters = []
		self.frames = []
		
		self.currentObj = None
		self.connectObj = None
		self.disconnectObj = None
	def FilterMake(self,filterName):
		# set shape's items
		shape = objFilter(x = self.shapesize / 2,
						  y = self.shapesize / 2,
						  shapeh = self.shapesize,
						  shapew = self.shapesize,
						  text = filterName, properties=[filterName])
		filter.make(shape)
						  
		bmp = wx.EmptyBitmap(self.shapesize,self.shapesize)
		dc = wx.MemoryDC()
		dc.SelectObject(bmp)
		dc.SetBackground(wx.Brush('#999999',wx.SOLID))
		dc.Clear()
		dc.SelectObject(wx.NullBitmap)
		
		shape.SetBitmap(bmp)
		
		shape.SetCanvas(self)
		
		self.filters.append(shape)
		self.AddShape(shape)
		
		evthandler = EvtHandler()
		evthandler.SetShape(shape)
		evthandler.SetPreviousHandler(shape.GetEventHandler())
		shape.SetEventHandler(evthandler)
		
		self.CanvasRedraw()
	def FilterDelete(self):
		self.DeleteShape()
	def ImageMake(self):
		if isinstance(self.currentObj,objImage):
			dlgView.ImageMakeView(self.frame,self.currentObj)
		else:
			shape = objImage(self.shapesize / 2,
							 self.shapesize / 2,
							 self.shapesize,
							 self.shapesize,"",None)
			shape.SetCanvas(self)
			self.images.append(shape)
			self.AddShape(shape)
			
			evthandler = EvtHandler()
			evthandler.SetShape(shape)
			evthandler.SetPreviousHandler(shape.GetEventHandler())
			shape.SetEventHandler(evthandler)
			
			dlgView.ImageMakeView(self.frame,shape)
		
		self.CanvasRedraw()
	def ImageOpen(self):
		file = dlgView.Open(self.frame)
		if file<>None:
			try:
				im = Image.open(file[0]).convert('RGB')
				
				shape = objImage(self.shapesize / 2,
								 self.shapesize / 2,
								 self.shapesize,
								 self.shapesize,"",im)
				
				shape.SetCanvas(self)
				self.images.append(shape)
				self.AddShape(shape)
				
				evthandler = EvtHandler()
				evthandler.SetShape(shape)
				evthandler.SetPreviousHandler(shape.GetEventHandler())
				shape.SetEventHandler(evthandler)
				
				self.CanvasRedraw()
			except IOError:
				self.frame.MessageError("Cannot open image!","Error")
	def ImageDelete(self):
		self.DeleteShape()
	def ImageView(self,obj):
		#self.frame.ImageView(obj)
		dlg = dlgView.ImageView(self.frame,obj)
		dlg.Show()
	def FilterView(self,obj):
		# this is a lazy way.
		if obj.properties == "score":
			dlg = dlgView.FilterView(self.frame, obj)
		else:
			dlg = dlgView.ScoreView(self.frame, obj)
		dlg.Show()
	def DeleteShape(self):
		dc = self.CanvasDC()
		
		if self.currentObj <> None:
			# unselect object
			self.currentObj.Select(False,dc)
			
			# Disconnect connected objects
			if isinstance(self.currentObj, objFilter):
				while len(self.currentObj.input) > 0:
					self.Disconnect(self.currentObj.input[0], self.currentObj)
			while len(self.currentObj.output) > 0:
				self.Disconnect(self.currentObj, self.currentObj.output[0])
			# Delete shape from canvas
			self.currentObj.EraseLinks(dc)
			self.currentObj.Erase(dc)
			self.currentObj.Delete()
			
			# Delete various kind shape
			if isinstance(self.currentObj, objImage):
				self.images.remove(self.currentObj)
			elif isinstance(self.currentObj, objFilter):
				self.filters.remove(self.currentObj)
			
			# Set currentObj None
			self.currentObj = None
			
			# Redraw
			self.CanvasRedraw()
		else:
			self.frame.MessageError('There is no selected object!','Error')
	def CanvasRedraw(self):
		dc = self.CanvasDC()
		
		self.diagram.ShowAll(True)
		self.diagram.Redraw(dc)
		self.Redraw(dc)
		self.SetFocus()
	def CanvasDC(self):
		dc = wx.ClientDC(self)
		self.PrepareDC(dc)
		return dc
	def Connects(self,fromShape,toShape):
		if isinstance(toShape, objImage):
			self.frame.MessageError('Cannot connect objects to the image!','Error')
			return None
		self._append(fromShape,toShape)
				
		# lines
		line = ogl.LineShape()
		line.SetCanvas(self)
		line.SetPen(wx.WHITE_PEN)
		line.SetBrush(wx.WHITE_BRUSH)
		line.AddArrow(ogl.ARROW_ARROW)
		line.MakeLineControlPoints(2)
		fromShape.AddLine(line,toShape)
		self.diagram.AddShape(line)
		line.Show(True)
		self.CanvasRedraw()
	def Disconnect(self,fromShape, toShape):
		dc = self.CanvasDC()
		lines = fromShape.GetLines()
		
		self._remove(fromShape,toShape)
		# lines
		for l in lines:
			if l.GetTo() == toShape:
				fromShape.RemoveLine(l)
				l.Erase(dc)
				l.Delete()
				break
		
		self.CanvasRedraw()
	def _append(self,fromS,toS):
		if toS.input.count(fromS) == 0:
			toS.input = toS.input+[fromS]
		if fromS.output.count(toS) == 0:
			fromS.output = fromS.output+[toS]
	def _remove(self,fromS,toS):
		if toS.input.count(fromS) == 1:
			toS.input.remove(fromS)
		if fromS.output.count(toS) == 1:
			fromS.output.remove(toS)
	def View(self,obj):
		view.View(self.frame,self.currentObj)
		
#------------------------------------------------------------------------------

class EvtHandler(ogl.ShapeEvtHandler):
	def __init__(self):
		ogl.ShapeEvtHandler.__init__(self)
	def OnLeftClick(self,x,y,keys=0, attachment = 0):
		shape = self.GetShape()
		canvas = shape.GetCanvas()
		
		dc = canvas.CanvasDC()
		
		if shape.Selected():
			canvas.currentObj = None
			shape.Select(False,dc)
			canvas.Redraw(dc)
		else:
			canvas.currentObj = shape
			shapeList = canvas.GetDiagram().GetShapeList()
			toUnselect = []
			for s in shapeList:
				if s.Selected():
					toUnselect.append(s)
			shape.Select(True,dc)
			
			if toUnselect:
				for s in toUnselect:
					s.Select(False,dc)
				canvas.Redraw(dc)
			
			### add line
			if canvas.connectObj <> None:
				canvas.Connects(canvas.connectObj,shape)
				canvas.connectObj = None
			
			### delete line
			if canvas.disconnectObj <> None:
				canvas.Disconnect(canvas.disconnectObj,shape)
				canvas.disconnectObj = None
	def OnRightClick(self,*ato_ha_muda):
		shape = self.GetShape()
		canvas = shape.GetCanvas()
		if isinstance(canvas.currentObj,objImage):
			dlg = canvas.ImageView(canvas.currentObj)
		if isinstance(canvas.currentObj,objFilter):
			dlg = canvas.FilterView(canvas.currentObj)
#------------------------------------------------------------------------------

class MainFrame(wx.Frame):
	def __init__(self):
		wx.Frame.__init__(self, None, -1,"ig2m")
		self.SetMenuBar(menuBar())
		self.editcount = 0
		
		self.canvas = MainCanvas(self)
		self.SetMenuBar(menuBar())
		
		self.SetEvents()
	def SetEvents(self):
		# Menu Events
		self.Bind(wx.EVT_MENU, self.FileNew,      id=FILE_NEW)
		self.Bind(wx.EVT_MENU, self.FileOpen,     id=FILE_OPEN)
		self.Bind(wx.EVT_MENU, self.FileSave,     id=FILE_SAVE)
		self.Bind(wx.EVT_MENU, self.FileSaveas,   id=FILE_SAVEAS)
		self.Bind(wx.EVT_MENU, self.FileExit,     id=FILE_EXIT)
		
		self.Bind(wx.EVT_MENU, self.ImageOpen, 	  id=IMAGE_OPEN)
		self.Bind(wx.EVT_MENU, self.ImageMake, 	  id=IMAGE_MAKE)
		self.Bind(wx.EVT_MENU, self.ImageDelete,  id=IMAGE_DELETE)
		self.Bind(wx.EVT_MENU, self.View,   	  id=IMAGE_VIEW)
		
		self.Bind(wx.EVT_MENU, self.FilterAnchor, id=FILTER_ANCHOR)
		self.Bind(wx.EVT_MENU, self.FilterBlend,  id=FILTER_BLEND)
		self.Bind(wx.EVT_MENU, self.FilterCopy,   id=FILTER_COPY)
		self.Bind(wx.EVT_MENU, self.FilterCrop,   id=FILTER_CROP)
		self.Bind(wx.EVT_MENU, self.FilterDC,     id=FILTER_DC)
		self.Bind(wx.EVT_MENU, self.FilterDESA,   id=FILTER_DESATURATE)
		self.Bind(wx.EVT_MENU, self.FilterI2G,    id=FILTER_I2G)
		self.Bind(wx.EVT_MENU, self.FilterMask,   id=FILTER_MASK)
		self.Bind(wx.EVT_MENU, self.FilterReplace, id=FILTER_REPLACE)
		self.Bind(wx.EVT_MENU, self.FilterResize, id=FILTER_RESIZE)
		self.Bind(wx.EVT_MENU, self.FilterRotate, id=FILTER_ROTATE)
		self.Bind(wx.EVT_MENU, self.FilterScore,  id=FILTER_SCORE)
		self.Bind(wx.EVT_MENU, self.FilterDelete, id=FILTER_DELETE)
		
		self.Bind(wx.EVT_MENU, self.Connects,     id=CONNECT_CONNECT)
		self.Bind(wx.EVT_MENU, self.Disconnect,   id=CONNECT_DISCONNECT)
				
		self.Bind(wx.EVT_MENU, self.Preferences,  id=OPTION_PREFERENCES)

		self.Bind(wx.EVT_MENU, self.MessageAbout, id=HELP_ABOUT)
	
	def FileNew(self,e):
		pass
	def FileOpen(self,e):
		pass
	def FileSave(self,e):
		pass
	def FileSaveas(self,e):
		pass
	def FileExit(self,e):	
		self.Destroy()
		
	def ImageOpen(self,e):
		self.canvas.ImageOpen()
	def ImageMake(self,e):
		self.canvas.ImageMake()
		self.canvas.diagram.ShowAll(True)
	def ImageDelete(self,e):
		self.canvas.ImageDelete()
	def View(self,e):
		if self.canvas.currentObj <> None:
			self.canvas.View(self.canvas.currentObj)
		
	def FilterAnchor(self,e):
		self.canvas.FilterMake("anchor")
	def FilterBlend(self,e):
		self.canvas.FilterMake("blend")
	def FilterCopy(self,e):
		self.canvas.FilterMake("copy")
	def FilterCrop(self,e):
		self.canvas.FilterMake("crop")
	def FilterDC(self,e):
		self.canvas.FilterMake("dc")
	def FilterDESA(self,e):
		self.canvas.FilterMake("desaturate")
		
	def FilterI2G(self,e):
		self.canvas.FilterMake("i2g")
	def FilterMask(self, e):
		self.canvas.FilterMake("mask")
	def FilterReplace(self,e):
		self.canvas.FilterMake("replace")
	def FilterResize(self,e):
		self.canvas.FilterMake("resize")
	def FilterRotate(self,e):
		self.canvas.FilterMake("rotate")
	def FilterScore(self,e):
		self.canvas.FilterMake("score")
	def FilterDelete(self,e):
		self.canvas.FilterDelete()
		
	def Connects(self,e):
		if self.canvas.currentObj <> None:
			self.canvas.connectObj = self.canvas.currentObj
	def Disconnect(self,e):
		if self.canvas.currentObj <> None:
			self.canvas.disconnectObj = self.canvas.currentObj
	def Preferences(self,e):
		pass
		
	def MessageAbout(self,e):
		dlg = wx.MessageDialog(self,
			'ig2m\n \
			image | grid to music composer\n\n \
			Copyright  2006  Takahiro Kamatani',
			'About',wx.OK | wx.ICON_INFORMATION)
		dlg.ShowModal()
		dlg.Destroy()
	def MessageError(self,text,title):
		dlg = wx.MessageDialog(self,text,title,wx.OK|wx.ICON_ERROR)
		dlg.ShowModal()
		dlg.Destroy()
	def get_editcount(self):
		self.editcount += 1 
		return self.editcount
class MainApp(wx.App):
	def OnInit(self):
		ogl.OGLInitialize()
		
		frame = MainFrame()
		self.SetTopWindow(frame)
		frame.Show(True)
		
		return True