# -*- coding: iso-8859-1 -*-
#	Programmer:	Antonio Barbosa
#	E-mail:		a_barbosa@users.sourceforge.net
#
#	Copyright 2007 Antonio Barbosa
#
#	Distributed under the terms of the GPL (GNU Public License)
#
#    DrPython 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 2 of the License, or
#    (at your option) any later version.
#
#    This program 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 this program; if not, write to the Free Software
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

#Plugin
#CodeMarksPlus
#Version 0.0.2 Antonio Barbosa 17 Fev 2007


import wx, wx.lib.dialogs
import os.path
import drPrefsFile

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



def OnAbout(DrFrame):
	NameAndVersion = """CodeMarksPlus:
Version: 0.0.2
a_barbosa@users.sourceforge.net

Enhanced version of CodeMarks of Daniel Pozmanter.

see: [Help]

Thanks to Daniel for his original Plugin.
Thanks to Franz Steinhaeusler for his suport and sugestions.
	"""
	AboutString = NameAndVersion + "By Antonio Barbosa\n\nReleased under the GPL."
	d = wx.lib.dialogs.ScrolledMessageDialog(DrFrame, AboutString, "About")
	d.ShowModal()
	d.Destroy()

def OnHelp(DrFrame):
	HelpString = """CodeMarksPlus Version: 0.0.2
Enhanced version of CodeMarks of Daniel Pozmanter.

	* Handles CodeMarks of multiple files.
	* Best with �myProject� plugin
	* With DoubleClick selects panel + code line
	* With RightClik: RemoveLine, Clear all, Close panel, show prefs, etc.
	* With Prefs: choose font and colors for display, panel position and
	name association for datafile + extension:.marks
"""
	d = wx.lib.dialogs.ScrolledMessageDialog(DrFrame, HelpString, "Help")
	d.ShowModal()
	d.Destroy(
	)
def str2tuple(s):
	""" Converts a string to tuple"""
	return tuple(int(z) for z in s[1:-1].split(','))

class CodeMarks:
	prefs = {
		'PanelPosition': 0 # Left panel
		,'OpenOnStart': 0
		,'SaveOption': 0 # AutoSave 0=Not 1=Use Script name 2=Use project name
		,'FontName': 'Arial'
		,'FontSize': 8
		,'FontWeight': wx.NORMAL
		,'FontStyle': wx.NORMAL
		,'ForeColor': (0,0,0) # Foreground Color
		,'BackColor': (255,255,255) # Background Color
	}

	def __init__(self, prefsfile):
		self.prefsfile = prefsfile
		self.readprefs()
		self.panel = None

	def readprefs(self):
		try:
			text = file(self.prefsfile, 'r').read()
			for pref, value in self.prefs.items():
				if type(value)==tuple:
					s=drPrefsFile.GetPrefFromText(value, text, pref, False)
					self.prefs[pref] = str2tuple(s)
				else:
					self.prefs[pref] = drPrefsFile.GetPrefFromText(value, text, pref, type(value)==type(1))
		except:
			print "ReadPrefs ERROR"
		
	def writeprefs(self):
		try:
			f = file(self.prefsfile, 'w')
			for pref, value in self.prefs.items():
				f.write("<%s>%s</%s>\n" % (pref, str(value), pref))
			f.close()
		except:
			print "writePrefs ERROR"
			f.close()

class PrefsDialog(wx.Dialog):
	def __init__(self, parent, id=-1, title="CodeMarksPlus Prefs",style=wx.DEFAULT_DIALOG_STYLE):
		wx.Dialog.__init__(self,parent,id, title)
		self.parent=parent
		prefs = parent.CodeMarks.prefs
		sizer = wx.BoxSizer(wx.VERTICAL)
		self.rbPosition = wx.RadioBox(self, -1, "Panel Position:",
			wx.DefaultPosition, wx.DefaultSize,
			['Left', 'Right'], 2, wx.RA_SPECIFY_COLS | wx.NO_BORDER)
		sizer.Add(self.rbPosition, 0, wx.EXPAND|wx.ALL, 4)
		
		
		self.rbSave = wx.RadioBox(self, -1, "Auto Save:",
			wx.DefaultPosition, wx.DefaultSize,
			["Don't save", "Use #1 script's name","Use project's name"], 2, wx.RA_SPECIFY_COLS | wx.NO_BORDER)
		sizer.Add(self.rbSave, 0, wx.EXPAND|wx.ALL, 4)
		self.chOpenOnStart = wx.CheckBox(self, -1, "Open On Start")
		sizer.Add(self.chOpenOnStart, 0, wx.EXPAND|wx.ALL, 4)
		
		box = wx.BoxSizer(wx.HORIZONTAL)
		btn1 = wx.Button(self ,-1,'Sel Font')
		btn2 = wx.Button(self ,-1,'ForeColor')
		btn3 = wx.Button(self ,-1,'BackColor')
		self.edText = wx.TextCtrl(self, -1, " 1234:1: Sample Text",size=(40,-1),style=wx.NO_BORDER)
		sizer.Add(self.edText, 1, wx.GROW|wx.ALL, 4)
		box.Add(btn1, 0, wx.ALIGN_CENTRE|wx.ALL, 4)
		box.Add(btn2, 0, wx.ALIGN_CENTRE|wx.ALL, 4)
		box.Add(btn3, 0, wx.ALIGN_CENTRE|wx.ALL, 4)
		sizer.Add(box, 0, wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.ALL, 4)
		btnsizer = wx.StdDialogButtonSizer()
		btnsizer.AddButton(wx.Button(self, wx.ID_OK))
		btnsizer.AddButton(wx.Button(self, wx.ID_CANCEL))
		btnsizer.Realize()
		sizer.Add(btnsizer, 0, wx.ALIGN_CENTER|wx.ALL, 4)
		self.SetSizer(sizer)
		sizer.Fit(self)

		self.Bind(wx.EVT_BUTTON, self.OnSelectFont, btn1)
		self.Bind(wx.EVT_BUTTON, self.OnSelectFColor, btn2)
		self.Bind(wx.EVT_BUTTON, self.OnSelectBColor, btn3)

		self.rbPosition.SetSelection(prefs['PanelPosition'])
		self.chOpenOnStart.SetValue(prefs['OpenOnStart'])
		self.rbSave.SetSelection(prefs['SaveOption'])

		font=wx.Font(8,wx.NORMAL,wx.NORMAL,wx.NORMAL)
		font.SetFaceName(prefs['FontName'])
		font.SetPointSize(prefs['FontSize'])
		font.SetWeight(prefs['FontWeight'])
		font.SetStyle(prefs['FontStyle'])

		self.edText.SetForegroundColour(prefs['ForeColor'])
		self.edText.SetBackgroundColour(prefs['BackColor'])
		self.edText.SetFont(font)
		self.curFColor=prefs['ForeColor']
		self.curBColor=prefs['BackColor']
		self.curFont = self.edText.GetFont()


	def OnSelectBColor(self, evt):
		dlg = wx.ColourDialog(self)
		if dlg.ShowModal() == wx.ID_OK:
			data = dlg.GetColourData()
			self.curBColor=data.GetColour().Get()
		dlg.Destroy()
		self.DisplaySampleText()

	def OnSelectFColor(self, evt):
		dlg = wx.ColourDialog(self)
		if dlg.ShowModal() == wx.ID_OK:
			data = dlg.GetColourData()
			self.curFColor=data.GetColour().Get()
		dlg.Destroy()
		self.DisplaySampleText()
		
	def OnSelectFont(self, evt):
		data = wx.FontData()
		data.EnableEffects(False)
		data.SetInitialFont(self.curFont)
		dlg = wx.FontDialog(self, data)
		if dlg.ShowModal() == wx.ID_OK:
			data = dlg.GetFontData()
			font = data.GetChosenFont()
			self.curFont = font
		dlg.Destroy()
		self.DisplaySampleText()

	def DisplaySampleText(self):
		self.edText.SetFont(self.curFont)
		self.edText.SetForegroundColour(self.curFColor)
		self.edText.SetBackgroundColour(self.curBColor)
		self.edText.Refresh()


class CodeMarksPanel(wx.Panel):
	def __init__(self, parent,grandparent):
		try:
			wx.Panel.__init__(self, parent)
			self.grandparent = grandparent #DrFrame
			self.prefs= grandparent.CodeMarks.prefs
			self.listCodeMarks = wx.ListBox(self)
			theSizer = wx.BoxSizer(wx.VERTICAL)
			theSizer.Add(self.listCodeMarks, 1, wx.EXPAND,1)

			self.SetAutoLayout(True)
			self.SetSizer(theSizer)

			self.listCodeMarks.Bind(wx.EVT_LISTBOX_DCLICK, self.OnCodemark)
			self.listCodeMarks.Bind( wx.EVT_RIGHT_DOWN, self.OnRightClick)
			
			font=wx.Font(11,wx.NORMAL,wx.NORMAL,wx.NORMAL)
			font.SetFaceName(self.prefs['FontName'])
			font.SetPointSize(self.prefs['FontSize'])
			font.SetWeight(self.prefs['FontWeight'])
			font.SetStyle(self.prefs['FontStyle'])
			self.listCodeMarks.SetForegroundColour(self.prefs['ForeColor'])
			self.listCodeMarks.SetBackgroundColour(self.prefs['BackColor'])
			self.listCodeMarks.SetFont(font)
			self._readCodeMarks()
		except:
			self.grandparent.ShowMessage("ERROR", "CODEMARKS")

	def AddCodemark(self, line, text):
		page=self.grandparent.documentnotebook.GetSelection()
		self.listCodeMarks.Append("%d:%d: %s" %(line+1,page,text))
		self._saveCodeMarks()
	
	def _saveCodeMarks(self):
		try:
			if self.prefs['SaveOption']==0:
				return
			if self.prefs['SaveOption']==1: #use name of 1st script
				s=self.grandparent.txtDocumentArray[0].filename
				fname =  s.split('.')[0]+'.marks'
			else: #use project's name
				s =  file(self.grandparent.pluginsdatdirectory + "/myproject.log", 'r').readline()
				fname =  s.split('.')[0]+'.marks'
			print '----->',fname
			text=self.listCodeMarks .GetStrings()
			f = file(fname, 'w')
			for line in text:
				f.write(line + "\n")
			f.close()
		except:
			self.grandparent.ShowMessage("SAVE ERROR", "CODEMARKS")

	def _readCodeMarks(self):
		try:
			if self.prefs['SaveOption']==0:
				return
			if self.prefs['SaveOption']==1: #use name of 1st script
				s=self.grandparent.txtDocumentArray[0].filename
				fname =  s.split('.')[0]+'.marks'
			else: #use project's name
				s =  file(self.grandparent.pluginsdatdirectory + "/myproject.log", 'r').readline()
				fname =  s.split('.')[0]+'.marks'
			if not os.path.exists(fname):
				return
			text=self.listCodeMarks .GetStrings()
			text = file(fname, 'r').readlines()
			self.listCodeMarks.Clear()
			for line in text:
				self.listCodeMarks.Append(line.strip())
		except:
			self.grandparent.ShowMessage("READ ERROR", "CODEMARKS")

	def OnClose(self,event):
		self.GetGrandParent().GetGrandParent().ClosePanel(self.PanelPosition, self.PanelIndex)
		
	def OnShowPrefs(self, event):
		OnPreferences(self.grandparent)

	def OnRemoveLine(self, event):
		i=self.listCodeMarks.GetSelection()
		if i<0:
			return
		self.listCodeMarks.Delete(i)
		self._saveCodeMarks()
		
	def OnClear(self, event):
		self.listCodeMarks.Clear()
		self._saveCodeMarks()
		
	def OnCodemark(self, event):
		s = self.listCodeMarks.GetStringSelection().split(':')
		line=int(s[0])-1
		page=int(s[1])
		self.grandparent.documentnotebook.SetSelection(page)
		self.grandparent.documentnotebook.SetTab()
		self.grandparent.txtDocument.ScrollToLine(line)
		self.grandparent.txtDocument.GotoLine(line)
		self.grandparent.txtDocument.EnsureCaretVisible()
		self.grandparent.txtDocument.SetFocus()

	def OnRightClick(self, event):
		ID_SHOW = self.grandparent.GetNewId()
		ID_REMOVE = self.grandparent.GetNewId()
		ID_CLEAR = self.grandparent.GetNewId()
		ID_CLOSE = self.grandparent.GetNewId()
		ID_PREFS = self.grandparent.GetNewId()
		menu = wx.Menu()
		menu.Append(ID_SHOW, "Show Line")
		self.grandparent.Bind(wx.EVT_MENU, self.OnCodemark, id=ID_SHOW)
		menu.Append(ID_REMOVE, "Remove Line")
		self.grandparent.Bind(wx.EVT_MENU, self.OnRemoveLine, id=ID_REMOVE)
		menu.Append(ID_CLEAR, "Clear List")
		self.grandparent.Bind(wx.EVT_MENU, self.OnClear, id=ID_CLEAR)
		menu.Append(ID_PREFS, "Show Prefs")
		self.grandparent.Bind(wx.EVT_MENU,self.OnShowPrefs, id=ID_PREFS)
		menu.Append(ID_CLOSE, "Close")
		self.grandparent.Bind(wx.EVT_MENU,self.OnClose, id=ID_CLOSE)
		
		(x,y) = self.grandparent.ScreenToClient(wx.GetMousePosition())
		self.grandparent.PopupMenu(menu, (x,y+40))
		menu.Destroy()
		
def OnPreferences(DrFrame):
	dlg = PrefsDialog(DrFrame)
	if dlg.ShowModal() == wx.ID_OK:
		prefs = DrFrame.CodeMarks.prefs
		prefs['PanelPosition'] = int(dlg.rbPosition.GetSelection())
		prefs['OpenOnStart'] = int(dlg.chOpenOnStart.GetValue())
		prefs['SaveOption'] = int(dlg.rbSave.GetSelection())
		prefs['FontName'] = dlg.curFont.GetFaceName()
		prefs['FontSize'] = dlg.curFont.GetPointSize()
		prefs['FontWeight'] = dlg.curFont.GetWeight()
		prefs['FontStyle'] = dlg.curFont.GetStyle()
		prefs['ForeColor'] = dlg.curFColor
		prefs['BackColor'] = dlg.curBColor
		DrFrame.CodeMarks.writeprefs()
		panel = DrFrame.CodeMarks.panel
		if panel:
			visible = DrFrame.mainpanel.IsVisible(panel.PanelPosition, panel.PanelIndex)
			panel.Close()
	dlg.Destroy()

def ToggleCodeMarks(self):
	panel = self.CodeMarks.panel
	if panel:
		self.mainpanel.ClosePanel(panel.PanelPosition, panel.PanelIndex)
	else:
		position = self.CodeMarks.prefs['PanelPosition']
		target, index = self.mainpanel.GetTargetNotebookPage(position, "CodeMarks")
		panel = CodeMarksPanel(target,self)
		target.SetPanel(panel)
		self.mainpanel.ShowPanel(position, index)
		self.CodeMarks.panel = panel
		panel.PanelPosition=position
		panel.PanelIndex=index

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

def Plugin(DrFrame):
	prefsfile = DrFrame.pluginspreferencesdirectory + "/CodeMarksPlus.preferences.dat"
	DrFrame.CodeMarks = CodeMarks(prefsfile)
	def onToggleCodeMarks(event):
		ToggleCodeMarks(DrFrame)

	def OnAddCodemark(event):
		try:
			panel = DrFrame.CodeMarks.panel
			if not panel:
				ToggleCodeMarks(DrFrame)
			line = DrFrame.txtDocument.GetCurrentLine()
			DrFrame.CodeMarks.panel.AddCodemark(line, DrFrame.txtDocument.GetLine(line).strip())
		except:
			DrFrame.ShowMessage("ERROR", "ADD CODEMARKS")
	if DrFrame.CodeMarks.prefs['OpenOnStart']:
		onToggleCodeMarks(None)

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


	ID_TOGGLE_CODEMARKS = DrFrame.GetNewId()
	ID_ADD_CODEMARK = DrFrame.GetNewId()

	DrFrame.Bind(wx.EVT_MENU, onToggleCodeMarks, id=ID_TOGGLE_CODEMARKS)
	DrFrame.Bind(wx.EVT_MENU, OnAddCodemark, id=ID_ADD_CODEMARK)
	
	DrFrame.AddPluginFunction("CodeMarksPlus", "Toggle CodeMarksPlus", onToggleCodeMarks)
	DrFrame.AddPluginFunction("CodeMarksPlus", "Add Codemark", OnAddCodemark)

	#Franz:
	DrFrame.AddPluginPopUpMenuFunction("CodeMarksPlus", "Toggle CodeMarksPlus", onToggleCodeMarks)
	DrFrame.AddPluginPopUpMenuFunction("CodeMarksPlus", "Add Codemark", OnAddCodemark)

	DrFrame.LoadPluginShortcuts('CodeMarksPlus')

	DrFrame.viewmenu.AppendSeparator()
	DrFrame.viewmenu.Append(ID_TOGGLE_CODEMARKS, DrFrame.GetPluginMenuLabel("CodeMarksPlus", "Toggle CodeMarksPlus", "Toggle CodeMarks"))
	DrFrame.viewmenu.Append(ID_ADD_CODEMARK, DrFrame.GetPluginMenuLabel("CodeMarksPlus", "Add Codemark", "Add Codemark"))

