##	Fonty Python Copyright (C) 2006, 2007, 2008, 2009 Donn.C.Ingle
##	Contact: donn.ingle@gmail.com - I hope this email lasts.
##
##	This file is part of Fonty Python.
##	Fonty Python 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 3 of the License, or
##	(at your option) any later version.
##
##	Fonty Python 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 Fonty Python.  If not, see <http://www.gnu.org/licenses/>.

import locale
import strings
import fpsys # Global objects
import fpversion

## Now, bring in all those big modules
import wx

## Setup wxPython to access translations : enables the stock buttons.
langid = wx.LANGUAGE_DEFAULT # Picks this up from $LANG
mylocale = wx.Locale( langid )

## Fetch my own pubsub stuff
from pubsub import *
ps = CPubsub()

## Fetch the dialogue classes *About, Settings, Help, etc.*
import dialogues

## DND: NB--Comments that have DND: in them mean DO NOT DELETE. They are used by me via grep on the cli.


from gui_Left import *
from gui_Middle import *
from gui_Right import *


class Splitter(wx.SplitterWindow):
	"""
	The splitter used twice in mainframe.
	"""
	def __init__(self, parent) :
		wx.SplitterWindow.__init__(self, parent, -1, style = wx.SP_LIVE_UPDATE | wx.SP_3D) 

class StatusBar(wx.StatusBar):
	"""
	The status bar
	"""
	def __init__(self, parent):
		wx.StatusBar.__init__(self, parent, -1)
		self.SetFieldsCount(1)
		self.SetStatusText( _("Welcome to Fonty Python version %s") % fpversion.version, 0)
	def Report(self, msg):
		self.SetStatusText(msg, 0)

class MainFrame(wx.Frame):
	"""
	The main frame for the app. Has some functionality for menu items.
	"""
	def __init__(self,parent,title) :
		## Draw the frame
		title = title + "   -   " + locale.getpreferredencoding()
		wx.Frame.__init__(self,parent,-1,title,fpsys.config.pos,fpsys.config.size) 
		
		## Try to show an icon
		try:
			image = wx.Image(fpsys.mythingsdir + 'fplogo.png', wx.BITMAP_TYPE_PNG) 
			image = image.ConvertToBitmap() 
			icon = wx.EmptyIcon() 
			icon.CopyFromBitmap(image) 
			self.SetIcon(icon) 
		except:
			pass

		## STATUS BAR
		self.sb = StatusBar(self)
		self.SetStatusBar(self.sb)
		
		## Prepare the menu bar
		self.menuBar = wx.MenuBar()

		## FILE MENU : Changed to "Tools" menu Sep 2009
		menu1 = wx.Menu()
		menu1.Append(101, _("&Settings\tCtrl+S"), _("Change settings"))
		menu1.AppendSeparator()
		## Jan 18 2008
		menu1.Append( 102, _("&Check fonts"), _("Find those fonts that crash Fonty.") )
		menu1.Append( 103, _("&Purge Pog"), _("Remove all ghost fonts from the selected Pog.") )
		
		self.MENUPURGE = menu1

		self.exit = menu1.Append(104, _("&Exit"), _("Close the app"))
		## Add menu to the menu bar
		self.menuBar.Append(menu1, _("&Tools"))


		## SELECT MENU: June 2009
		menu3 = wx.Menu()
		menu3.Append( 301, _("&Select ALL the source fonts"), _("Select ABSOLUTELY ALL the fonts in the chosen source."))
		menu3.Append( 302, _("&Clear ENTIRE selection"), _("Clear the selection completely.") )
		## Add menu to the menu bar
		self.menuBar.Append(menu3, _("&Selection"))
		self.MENUSELECTION = menu3

		## HELP MENU
		menu2 = wx.Menu() 
		menu2.Append(201, _("H&elp\tF1"))
		menu2.Append(202, _("&About"))
		## Append 2nd menu
		self.menuBar.Append(menu2, _("&Help"))

		## Tell the frame the news
		self.SetMenuBar(self.menuBar)

		## Setup the ESC key and the LEFT / RIGHT keys
		accel = wx.AcceleratorTable([
			(wx.ACCEL_NORMAL, wx.WXK_ESCAPE, self.exit.GetId()),
			(wx.ACCEL_CTRL, wx.WXK_RIGHT, wx.ID_FORWARD),
			(wx.ACCEL_CTRL, wx.WXK_LEFT, wx.ID_BACKWARD)
			])
		self.SetAcceleratorTable(accel)

		## Bind the Left and Right key shortcuts.	
		self.Bind(wx.EVT_MENU, self.OnAccelKey, id=wx.ID_FORWARD )
		self.Bind(wx.EVT_MENU, self.OnAccelKey, id=wx.ID_BACKWARD )

		## The X close window button.
		self.Bind( wx.EVT_CLOSE, self.onHandleESC )
	
		## Bind events for the menu items
		self.Bind(wx.EVT_MENU, self.onHandleESC, self.exit)
		self.Bind(wx.EVT_MENU, self.menuSettings, id = 101)
		self.Bind(wx.EVT_MENU, self.menuCheckFonts, id = 102 )
		self.Bind(wx.EVT_MENU, self.menuPurgePog, id = 103 )
		self.Bind(wx.EVT_MENU, self.menuAbout, id = 202)
		self.Bind(wx.EVT_MENU, self.menuHelp, id = 201)
		# June 2009
		self.Bind(wx.EVT_MENU, self.menuSelectionALL, id=301)
		self.Bind(wx.EVT_MENU, self.menuSelectionNONE, id=302)
		
		## Create a splitter 
		self.splitter = Splitter(self) 
	
		## The notebook
		self.panelNotebook = wx.Panel(self.splitter) 
		
		## Notebook label and icon
		self.viewIcon = wx.StaticBitmap( self.panelNotebook, -1, wx.Bitmap( fpsys.mythingsdir + 'icon_source_16x16.png', wx.BITMAP_TYPE_PNG ))		
		self.viewLabel = wx.StaticText( self.panelNotebook, -1, _("Source, Folder or Pog"), style = wx.ALIGN_LEFT )
		self.viewLabel.SetFont( wx.Font(10, fpsys.DFAM, wx.NORMAL, wx.FONTWEIGHT_BOLD) )
		
		## A horiz sizer to hold the icon and text
		self.sizer_iconandtext = wx.BoxSizer(wx.HORIZONTAL)
		self.sizer_iconandtext.Add( (4, 1), 0 )
		self.sizer_iconandtext.Add( self.viewIcon, 0, wx.TOP | wx.BOTTOM, border = 4 )
		self.sizer_iconandtext.Add( self.viewLabel, 1, wx.EXPAND | wx.TOP | wx.BOTTOM | wx.LEFT, border = 4 )
		
		## Now the actual notebook
		self.nb = NoteBook(self.panelNotebook)

		## Make a Vertical sizer to hold them.
		self.sizerNotebook = wx.BoxSizer(wx.VERTICAL)
		
		## Add them to the sizer.
		self.sizerNotebook.Add(self.sizer_iconandtext, 0, wx.EXPAND)
		self.sizerNotebook.Add(self.nb,1,wx.EXPAND) 
		
		self.panelNotebook.SetSizer(self.sizerNotebook) 
		self.sizerNotebook.Layout() 
		
		## dec 2007 : Added a second splitter. It was a bitch!
		self.splitter2 = Splitter(self.splitter) # gets the second slot of splitter
		
		## Font View Panel Control:
		self.fontViewPanel = FontViewPanel(self.splitter2) # first slot in splitter2
		
		self.sizerFontView  = wx.BoxSizer(wx.VERTICAL) 
		self.sizerFontView.Add(self.fontViewPanel, 1, wx.EXPAND)
		self.sizerFontView.SetDimension( 0, 0, 1024, 0)
		#self.fontViewPanel.Layout()
	   
		## THE FAR RIGHT HAND SIDE
		## The TargetPogChooser
		self.panelTargetPogChooser = TargetPogChooser(self.splitter2) # last slot of splitter2

		self.sizerRight = wx.BoxSizer(wx.HORIZONTAL)
		self.sizerRight.Add(self.panelTargetPogChooser, 1, wx.EXPAND)
		self.panelTargetPogChooser.Layout()
		
		self.splitter.SetMinimumPaneSize(64) 
		self.splitter.SplitVertically( self.panelNotebook, self.splitter2, fpsys.config.leftSash )
		
		self.splitter2.SetMinimumPaneSize(128)
		self.splitter2.SplitVertically( self.fontViewPanel, self.panelTargetPogChooser) #Don't suggest a size here.

		self.SetCursor(wx.StockCursor(wx.CURSOR_ARROW))
		
		## Now to subscribe to have my various def called from other places:
		ps.sub(show_error, self.ErrorBox) ##DND: class MainFrame
		ps.sub(show_error_and_abort, self.ErrorAbort) ##DND: class MainFrame
		ps.sub(show_message, self.MessageBox) ##DND: class MainFrame
		ps.sub(print_to_status_bar, self.StatusbarPrint) ##DND: class MainFrame
		## Dec 2007 - Used on middle click in gui_Fitmap.py
		ps.sub( menu_settings, self.menuSettings ) ##DND: class MainFrame
		ps.sub( toggle_selection_menu_item, self.toggleSelectionMenuItem ) ##DND: class MainFrame

		ps.sub( toggle_purge_menu_item, self.TogglePurgeMenuItem ) ##DND: class MainFrame

		## call the big one - the big chief, the big cheese:
		## This eventually draws all the Fitmaps - giving the middle have a width.
		ps.pub( update_font_view ) #DND: It's in gui_Middle.py under class FontViewPanel
	
		self.splitter.Bind(wx.EVT_SPLITTER_SASH_POS_CHANGED, self.onSize) #Give splitter an event (not splitter2) weird.

		# Force splitter2 to the correct position. 
		self.splitter2.SetSashPosition( -fpsys.config.rightSash, redraw=False )

		self.Layout()

		## A nasty looking line to call the SortOutTheDamnImages function
		## This is to draw the right icons depending on the params from cli.
		self.panelTargetPogChooser.pogTargetlist.SortOutTheDamnImages(False)

	def OnAccelKey(self,evt):
		ps.pub( left_or_right_key_pressed, evt ) #fwd this business on-to a func in gui_Middle.py


	def toggleSelectionMenuItem(self, onoff):
		#HIG says to leave top menu alone and only toggle sub-items.
		self.MENUSELECTION.Enable(301,onoff[0])
		self.MENUSELECTION.Enable(302,onoff[0])

	def onSize( self, evt ):
		"""
		The splitter has been moved. Don't ask me why splitter and not splitter2
		is the one we have to use. Go figure.
		"""
		ps.pub( update_font_view ) # starts a chain of calls.
		
	def GetSashesPos( self, args=None ):
		## For saving/restoring the sashes to where we bloody left them :\
		return ( self.splitter.GetSashPosition(), self.panelTargetPogChooser.GetClientSize()[0])
		
	def StatusbarPrint(self, args):
		self.sb.Report(args[0])

	def MessageBox(self, args):
		dlg = wx.MessageDialog(self, args[0] , _("Warning"), wx.OK | wx.ICON_INFORMATION)
		dlg.ShowModal()
		dlg.Destroy()
	def ErrorBox(self, args):
		dlg = wx.MessageDialog(self, args[0], _("Error"), wx.OK | wx.ICON_ERROR)
		dlg.ShowModal()
		dlg.Destroy()
	def ErrorAbort(self, args):
		self.ErrorBox(args) #Pass it along to be displayed
		self.endApp()
		
	def onHandleESC(self, e) :
		print strings.done
		self.endApp() 

	def endApp(self) :
		"""
		Save app's vital statistics and exit.
		See the end of start.py where it's actually saved.
		"""
		fpsys.config.pos = self.GetPositionTuple() 
		## Dec 2007 - I was using the wrong func and the
		## main window kept getting smaller!
		fpsys.config.size = self.GetSizeTuple()
		fpsys.config.leftSash, fpsys.config.rightSash = self.GetSashesPos()
		##June 2009 - fetch and record the value of the recurse folders checkbox.
		fpsys.config.recurseFolders = app.GetTopWindow().nb.recurseFolders.GetValue()
		self.Destroy() 
   
	def menuSettings(self, e):
		lastnuminpage, lastpoints, lasttext = fpsys.config.numinpage ,fpsys.config.text, fpsys.config.points
		dlg = dialogues.DialogSettings(self)
		val = dlg.ShowModal()
		if val == wx.ID_OK:
			## Did anything change?
			num = int(dlg.inputPageLen.GetValue())
			points = int(dlg.inputPointSize.GetValue())
			txt = dlg.inputSampleString.GetValue()
			ignoreAdjust = dlg.chkAdjust.GetValue() #Sept 2009
			if (num, txt, points) != (lastnuminpage, lastpoints, lasttext):
				fpsys.config.numinpage = int(num)
				fpsys.config.points = int(points)
				if len(txt) > 0: fpsys.config.text =  txt
			
			fpsys.config.ignore_adjustments = ignoreAdjust #Sept 2009
			fpsys.config.CMC.SET_CURRENT_APPNAME( dlg.CHOSEN_CHARACTER_MAP) # Oct 2009
			
			## Now to refresh things:
			## Sept 2009 : size change means we need new values for fitmaps
			ps.pub( reset_top_left_adjustments ) ##DND : In ScrolledFontView
			ps.pub( update_font_view )
		dlg.Destroy()

	def menuAbout(self, e):
		dlg =dialogues.DialogAbout(self)
		val = dlg.ShowModal()
		dlg.Destroy()
		
	def menuHelp(self, e):
		dlg = dialogues.DialogHelp(self, size=(800, 600))
		val = dlg.ShowModal()
		dlg.Destroy()

	def menuCheckFonts( self, e ):
		"""
		Added Jan 18 2008
		User can visit suspicious directories with this tool
		to gather a list of fonts that kill the app. They will be
		marked as such and hereafter be safe to use.
		"""
		## Set startdir to the one our own dircontrol is in
		if fpsys.state.viewpattern == "F": 
			startdir = fpsys.state.viewobject.path
		else: 
			##Let's get it from the config object
			startdir = fpsys.config.lastdir
		dlg = dialogues.DialogCheckFonts( self, startdir )
		val = dlg.ShowModal()
		dlg.Destroy()

	def menuSelectionALL(self,e):
		if not fpsys.state.cantick: return # Can't tick if this is False.
		fpsys.state.numticks=0
		vo=fpsys.state.filteredViewObject # We want to select what is FILTERED
		for fi in vo:
			if not fi.inactive:
				fi.ticked=True
				fpsys.state.numticks += 1
		## Now update the view
		ps.pub( update_font_view )	

	def menuSelectionNONE(self,e):
		fpsys.state.numticks=0
		vo=fpsys.state.viewobject # We *REALLY* mean select NONE. So ignore filter.
		for fi in vo:
			if not fi.inactive:
				fi.ticked=False
		## Now update the view
		ps.pub( update_font_view )	

	def TogglePurgeMenuItem(self, vis):
		vis=vis[0]
		self.MENUPURGE.Enable(103,vis)
	
	def menuPurgePog(self,e):
		##The menu item only becomes active for Pogs that are not installed,
		##so we can purge without further tests:
		pogname = fpsys.state.viewobject.name
		dlg = wx.MessageDialog(self,_("Do you want to purge %s?\n\nPurging means all the fonts in the pog\nthat are not pointing to actual files\nwill be removed from this pog.") % pogname, _("Purge font?"), wx.YES_NO | wx.ICON_INFORMATION )
		if dlg.ShowModal() == wx.ID_YES:
			## pog.purge() Raises
			##		  PogEmpty
			##		  PogInstalled
			try:
				fpsys.state.viewobject.purge()
			except(fontybugs.PogEmpty, fontybugs.PogInstalled),e:
				ps.pub(show_error, unicode( e ))
				ps.pub(print_to_status_bar, _("%s has not been purged.") % pogname)
				return 

			## Update GUI
			ps.pub(print_to_status_bar, _("%s has been purged.") % pogname)

			ps.pub(update_font_view)

##http://wiki.wxpython.org/Widget%20Inspection%20Tool
## Use ctrl+alt+i to open it.
#import wx.lib.mixins.inspection
## Start the main frame and then show it.
class App(wx.App ):#, wx.lib.mixins.inspection.InspectionMixin) :
	def OnInit(self):
		#self.Init()  # initialize the inspection tool
		
		## Initial dialogue to inform user about their potential fate:
		if not "unicode" in wx.PlatformInfo:
			wx.MessageBox(_("I am sorry, but Unicode is not supported by this installation of wxPython. Fonty Python relies on Unicode and will simply not work without it.\n\nPlease fetch and install the Unicode version of python-wxgtk."), caption=_("SORRY: UNICODE MUST BE SUPPORTED"), style=wx.OK | wx.ICON_EXCLAMATION )
			raise SystemExit

		bmp=wx.Image(fpsys.mythingsdir + "splash.png",wx.BITMAP_TYPE_PNG).ConvertToBitmap()
		ss=wx.SplashScreen( bmp, wx.SPLASH_CENTRE_ON_SCREEN, 1, None, -1)

		## Oct 2009
		##  this is the only place I can get the system font family
		fpsys.DFAM = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT).GetFamily()

		frame = MainFrame(None, _("Fonty Python: bring out your fonts!"))
		self.SetTopWindow(frame) 
		
		frame.Show(True) 
		ss.Close()

		return True
## app
app = App(0) 
		
## start 
app.MainLoop() 
