def onSelect(self, e):
        """
        pognochange: means No change to the selected Pog.
        """
        wx.BeginBusyCursor()
        self.indexselected = e.m_itemIndex
        pognochange = False
        if self.indexselected == self.lastindexselected:
            ## We have clicked on the same Pog as last time
            ## - ergo do nothing.
            pognochange = True
        # Record this for next time around
        self.lastindexselected = self.indexselected

        # Gets UNICODE !!!
        textpogname = self.GetItemText(self.indexselected)

        if self.whoami == "SOURCEPOG":
            ps.pub(source_pog_has_been_selected, textpogname, pognochange)
        else:
            ps.pub(target_pog_has_been_selected, textpogname, pognochange)

        self.toggle_list_icons_according_to_selection(pognochange)

        wx.EndBusyCursor()
Exemple #2
0
 def multiClick(self, e):
     ## NEW
     if e.GetId() == self.idnew:
         ## New Pog button pressed
         dlg = wx.TextEntryDialog(self, _("Enter a name for the new Pog"),
                                  _("New Pog"), _("Fonty Python"))
         dlg.SetValue("")
         if dlg.ShowModal() == wx.ID_OK:
             nam = dlg.GetValue()
             if nam == "":
                 ps.pub( show_message, _(
                     "A Pog with no name won't be created, "\
                     "however it was a good try!") )
             ## Is it unique?
             elif fpsys.isPog(nam):
                 ## Nope, it's there already
                 ps.pub(show_message,
                        _("\"{}\" already exists.").format(nam))
             else:
                 ## We have a winner.
                 ## Make a pog object and then write it,
                 ipog = fontcontrol.Pog(nam)
                 try:
                     ipog.write()
                 except fontybugs.PogWriteError, e:
                     ps.pub(show_error_and_abort, unicode(e))
                 del ipog
                 ## Now put it into the list
                 self.pogTargetlist.AddItem(nam)
                 #ps.pub(add_item_to_notebook, nam)
                 ps.pub(add_pog_item_to_source, nam)
                 ps.pub(update_font_view)
         dlg.Destroy()
         return
Exemple #3
0
    def onClick(self, event) :
        """
        Deals with clicks on self.
        Charmap button is a sub-test on a rect.
        This refreshes the underlying bitmap and DOES NOT cause the
        chain update_font_view (in gui_FontView) to run.
        """
        if self.cmb_overout.truthstate and self.can_have_button():
            self.openCharacterMap()
            return

        ## Prevent a click that would APPEND a ghost font.
        cannot_tick = fpsys.state.action == "APPEND" and self.fitem.badstyle == "FILE_NOT_FOUND"
        if cannot_tick:
            return

        if fpsys.state.cantick and not self.fitem.inactive:
            self.fitem.ticked = not(self.fitem.ticked)
            self.assemble_bitmap() # This only redraws a single font item.
            self.Refresh()  #forces onPaint()

            ## Inc or dec a counter depending on the tickedness of this item
            if self.fitem.ticked: fpsys.state.numticks += 1
            if not self.fitem.ticked: fpsys.state.numticks -= 1
            ps.pub(toggle_main_button)
Exemple #4
0
    def ToggleMainButton(self):

        # both on, then off .. if
        ps.pub(toggle_selection_menu_item, True)
        self.button_main.Enable(True)

        self.button_main.SetLabel(self.buttMainLastLabel)
        #print "In ToggleMainButton, testing action:", fpsys.state.action
        if fpsys.state.action == "NOTHING_TO_DO":
            self.button_main.Enable(False)
            ps.pub(toggle_selection_menu_item, False)
            return

        if fpsys.state.numticks == 0:
            self.button_main.Enable(False)
Exemple #5
0
 def OnPogTargetClick(self, args):
     """
     args[0] pogname
     args[1] is pognochange
     """
     ## Made it so a second click on a target pog
     ## will unselect it.
     if args[1]:  #pognochange = True, so let's deselect this pog
         self.SelectNoTargetPog()
         ps.pub(update_font_view)
         return
     try:
         fpsys.instantiateTargetPog(args[0])
     except fontybugs.PogInvalid, e:
         ps.pub(show_error_and_abort, unicode(e))
         return
    def OnViewPogClick(self, args):
        """
        args[0] is pogname, args[1] is pognochange
        """
        # Dec 2017: Force no-selection in dir control
        # so the gui's visual "logic" makes sense: I.e we
        # are now looking at a Pog, not a Folder any more.
        self.tree.UnselectAll()

        ## Check pognochange, it means this is the same pog as last time.
        if args[1]: return

        ## instantiateViewPog calls pog.genList which bubbles:
        ## PogInvalid
        ## BUT - this error only makes sense from the
        ## cli pov. By the time the gui is running, that
        ## pog has been renamed .badpog and therefore 
        ## won't even appear in the list. So, don't bother
        ## catching it.
        fpsys.instantiateViewPog(args[0])

        if fpsys.state.samepogs: #forbid same pogs selection
            ps.pub(clear_targetpog_selection)
        else:
            ps.pub(reset_to_page_one)
        ps.pub(update_font_view)
Exemple #7
0
    def onMainClick(self, evt):
        """
        Removes fonts, or Appends fonts. Depends on situation in fpsys.state
        """
        #Saved by Robin Dunn, once again ! ! !
        xPos, yPos = self.scrolledFontView.GetViewStart()
        wx.BeginBusyCursor()
        doupdate = False

        ## Let's determine what kind of thing to do:
        if fpsys.state.action == "REMOVE":
            ## We have a pog in viewobject and we must remove the
            ## selected fonts from it.
            vo = fpsys.state.viewobject
            victims = []
            dowrite = False
            for fi in vo:
                if fi.ticked:
                    victims.append(fi)  #Put it into another list
                    dowrite = True
            for fi in victims:
                vo.remove(fi)  #Now remove it from the vo
            del victims

            if dowrite:
                fpsys.flushTicks()
                bug = False
                try:
                    vo.write()
                except (fontybugs.PogWriteError), e:
                    bug = True
                    ps.pub(show_error, unicode(e))

                doupdate = True

                if not bug:
                    ps.pub(print_to_status_bar,
                           _("Selected fonts have been removed."))
                else:
                    ps.pub(print_to_status_bar,_(
                        "There was an error writing the pog "\
                        "to disk. Nothing has been done."))
Exemple #8
0
class TargetPogChooser(wx.Panel):
    """
    Chooses target pogs. Houses control buttons.
    """
    def __init__(self, parent, id_zip_pog_button):
        wx.Panel.__init__(self, parent, id=-1)

        target_icon = fpwx.icon(self, 'icon_target')
        target_label = fpwx.large_label(self, _("Target Pogs"))

        s = None
        if fpsys.state.targetpattern == "P":
            s = fpsys.state.targetobject.name

        ## The actual list control
        self.pogTargetlist = PogChooser(self, whoami="TARGETPOG", select=s)

        ## Subscriptions:
        ps.sub(target_pog_has_been_selected,
               self.OnPogTargetClick)  ##DND: class TargetPogChooser
        ps.sub(clear_targetpog_selection,
               self.SelectNoTargetPog)  ##DND: class TargetPogChooser

        ## The "no pog" button
        self.idnone = wx.NewId()
        self.buttNoPog = wx.Button(self,
                                   label=_("Clear selection"),
                                   id=self.idnone)
        #self.buttNoPog = wx.BitmapButton(self, self.idnone,
        #        fpwx.wxbmp( "icon_X" ) )#, style = wx.NO_BORDER)
        self.buttNoPog.SetToolTipString(_("Deselects any chosen Pogs."))

        ## The buttons under the pog list
        ## Giving them all id numbers so my single handler can tell them apart.
        self.idnew = wx.NewId()
        self.idinstall = wx.NewId()
        self.iduninstall = wx.NewId()
        self.iddelete = wx.NewId()

        ## Buttons will be handled in wxgui, so we pass ids in __init__
        self.idzip = id_zip_pog_button

        self.buttNew = wx.Button(self, label=_("New Pog"), id=self.idnew)
        self.buttNew.SetToolTipString(_("Creates a new, empty Pog"))

        self.buttInstall = wx.Button(self,
                                     label=_("Install Pog(s)"),
                                     id=self.idinstall)
        self.buttInstall.SetToolTipString(
            _("Installs all selected Pogs.\n{}").format(
                strings.ctrl_select_msg))

        self.buttUninstall = wx.Button(self,
                                       label=_("Uninstall Pog(s)"),
                                       id=self.iduninstall)
        self.buttUninstall.SetToolTipString(
            _("Uninstalls all selected Pogs.\n{}").format(
                strings.ctrl_select_msg))

        self.buttDelete = wx.Button(self,
                                    label=_("Delete Pog(s)"),
                                    id=self.iddelete)
        self.buttDelete.SetToolTipString(_("Deletes the selected Pog(s)"))

        self.buttZip = wx.Button(self, label=_("Zip Pog(s)"), id=self.idzip)
        self.buttZip.SetToolTipString(
            _("Save a zip file of the selected Pog(s)"))
        self.list_of_target_pogs_selected = None  # will be used in wxgui

        mainvs = wx.BoxSizer(wx.VERTICAL)
        self.iconandtext = wx.BoxSizer(wx.HORIZONTAL)
        self.iconandtext.Add(target_icon,
                             0,
                             wx.TOP | wx.BOTTOM | wx.LEFT,
                             border=4)
        self.iconandtext.Add(target_label,
                             1,
                             wx.LEFT | wx.BOTTOM | wx.ALIGN_BOTTOM,
                             border=4)
        mainvs.Add(self.iconandtext, 0, wx.EXPAND)

        mainvs.Add(self.pogTargetlist, 1, wx.EXPAND)

        ## The buttons under the target:
        gs = wx.GridSizer(3, 2)
        gs.AddMany([
            (self.buttNoPog, 1, wx.EXPAND),
            (self.buttZip, 1, wx.EXPAND),
            (self.buttInstall, 1, wx.EXPAND),
            (self.buttUninstall, 1, wx.EXPAND),
            (self.buttNew, 1, wx.EXPAND),
            (self.buttDelete, 1, wx.EXPAND),
        ])

        mainvs.Add(gs, 0, wx.EXPAND)

        self.SetSizer(mainvs)

        ## Bind the events:
        e = wx.EVT_BUTTON  # was wx.EVT_LEFT_UP
        self.buttNoPog.Bind(e, self.multiClick)
        self.buttNew.Bind(e, self.multiClick)
        self.buttInstall.Bind(e, self.multiClick)
        self.buttUninstall.Bind(e, self.multiClick)
        self.buttDelete.Bind(e, self.multiClick)
        self.buttZip.Bind(e, self.multiClick)

        self.toggleButtons()

    ## Catch all the button clicks on the control.
    def multiClick(self, e):
        ## NEW
        if e.GetId() == self.idnew:
            ## New Pog button pressed
            dlg = wx.TextEntryDialog(self, _("Enter a name for the new Pog"),
                                     _("New Pog"), _("Fonty Python"))
            dlg.SetValue("")
            if dlg.ShowModal() == wx.ID_OK:
                nam = dlg.GetValue()
                if nam == "":
                    ps.pub( show_message, _(
                        "A Pog with no name won't be created, "\
                        "however it was a good try!") )
                ## Is it unique?
                elif fpsys.isPog(nam):
                    ## Nope, it's there already
                    ps.pub(show_message,
                           _("\"{}\" already exists.").format(nam))
                else:
                    ## We have a winner.
                    ## Make a pog object and then write it,
                    ipog = fontcontrol.Pog(nam)
                    try:
                        ipog.write()
                    except fontybugs.PogWriteError, e:
                        ps.pub(show_error_and_abort, unicode(e))
                    del ipog
                    ## Now put it into the list
                    self.pogTargetlist.AddItem(nam)
                    #ps.pub(add_item_to_notebook, nam)
                    ps.pub(add_pog_item_to_source, nam)
                    ps.pub(update_font_view)
            dlg.Destroy()
            return

        ## A list of multiple-selected pog names:
        tl = self.pogTargetlist
        multipogs = [
            tl.GetItemText(i) for i in xrange(tl.GetItemCount())
            if tl.IsSelected(i)
        ]

        ## DELETE
        if e.GetId() == self.iddelete:
            ## Selected Pog(s) to be deleted:
            tokill = multipogs
            iPogsToKill = []
            ##Is any one of those installed?
            allok = True
            for p in tokill:
                ## Michael Hoeft tested pog delete and noticed the bug. Thanks.
                ## Fixed Oct 2009
                iPog = fontcontrol.Pog(p)
                if iPog.isInstalled():
                    ps.pub( show_error, _(
                        "One or more selected Pogs is installed, " \
                        "fix your selection and try again.") )
                    allok = False
                    break
                iPogsToKill.append(iPog)

            if allok:
                ## Build a string for reporting in the dialog
                if len(tokill) > 1:
                    pogname = ""
                    for f in tokill[:-1]:
                        pogname += u'"{}", '.format(f)
                    #We want "remove "blah", "bloop". Are you sure?"
                    pogname = u'{} "{}"'.format(pogname, tokill[-1])
                else:
                    pogname = u'"{}"'.format(tokill[0])

                dlg = wx.MessageDialog(
                    self,
                    _("Remove {}. Are you sure?").format(pogname),
                    _("Are you sure?"), wx.YES_NO | wx.ICON_INFORMATION)
                if dlg.ShowModal() == wx.ID_YES:
                    ## Let's do them in:
                    for victim in iPogsToKill:  #tokill:
                        ## Now kill the file on disk:
                        try:
                            victim.delete()
                        except fontybugs.PogCannotDelete, e:
                            ps.pub(show_error, unicode(e))
                            return
                        ## Remove from the lists:
                        self.pogTargetlist.RemoveItem(victim.name)
                        ps.pub(remove_pog_item_from_source, victim.name)

                        ## What if it was ALSO our view object?
                        if fpsys.state.viewobject.label() == victim.name:
                            ## It was! We must declare it Empty.
                            fpsys.SetViewPogToEmpty()

                    ## Now re-draw things
                    ps.pub(update_font_view)
                    dlg.Destroy()

                    ## Select no pog.
                    self.SelectNoTargetPog()
            return
Exemple #9
0
                            fpsys.SetViewPogToEmpty()

                    ## Now re-draw things
                    ps.pub(update_font_view)
                    dlg.Destroy()

                    ## Select no pog.
                    self.SelectNoTargetPog()
            return

        ## NO POG pressed
        if e.GetId() == self.idnone:
            ## Select No Pog button pressed
            if fpsys.state.targetobject is None: return  #Already done.
            self.SelectNoTargetPog()
            ps.pub(update_font_view)
            return  #No need to tell mainframe about this.

        ## Prepare for Install/Uninstall POG

        ## install or uninstall all selected pogs - caters for multiple pog selections
        ## the instantiateTargetPog must be called on each pog-name in the list
        ## to setup the globals in fpsys. This is new from my previous one-selection only
        ## code which assumed that instantiateTargetPog had been called already (when pog
        ## was selected by the mouse)

        ## Install
        if e.GetId() == self.idinstall:
            wx.BeginBusyCursor()
            for p in multipogs:
                fpsys.instantiateTargetPog(
Exemple #10
0
    def MainFontViewUpdate(self):
        """
        Vital routine - the heart if the app.

        This decides what to do based on what has been selected.
        It draws the controls and the fonts as appropriate.
        It also sets flags in fpsys.state
        """

        ## If any DismissablePanels are open, hide them:
        ps.pub(ensure_fontview_shown)

        ## Get shorter vars to use.
        V = fpsys.state.viewobject
        T = fpsys.state.targetobject

        VC = fpsys.state.viewpattern  # View Char
        TC = fpsys.state.targetpattern  # Target Char

        P = VC + TC  # a two-char flag

        ## Okay, let's make a key:..

        ## [S][rw][T][rws] <-- key's basic shape
        ## Where S is Source, T is Target:
        ##  E == Empty View/Source - no fonts in chosen Source.
        ##  N == Empty Target - no fonts.
        ##  P is Pog
        ##  F is Folder
        ## And rw:
        ## r is read (i.e. only can view)
        ## w is write (i.e. remove or append)
        ## s is same (S/T pogs are the same)
        ## Example:
        ## PrN -> Source pog+read. No target pog.
        ##     i.e: We are viewing a pog that is installed
        ##     (no write.)
        ## FPw -> Source folder. Target pog+write
        ##     i.e. We are viewing a folder and have a Pog
        ##     which is *not* installed, so can be 'written'
        ##     i.e. have fonts appended.

        # EN -> EN (Empty source, No target)
        # EP -> EP (Empty source, Pog target (weird) )
        # FN -> FN (Folder source, No target)
        if P in ('EN', 'EP', 'FN'):
            key = P

        # PN -> PrN or PwN
        # Pog source, No target.
        # Because 1) source is a Pog
        #     and 2) there's no target,
        # the Pog can be:
        #  r = view it only (i.e. it's installed)
        #  w = remove fonts
        elif P == "PN":
            key = "PrN" if V.isInstalled() else "PwN"

        # FP -> FPr or FPw
        # Folder source, Pog target. Target r or w.
        # Similar logic. If target pog is installed
        # it can't be added-to, i.e. it's 'r' only.
        # else it can be 'w'
        elif P == "FP":
            key = "FPr" if T.isInstalled() else "FPw"

        # PP -> PPr or PPw or PPs
        # Target pog is either 'r' or 'w' or ...
        # Target pog 's' means source and target are same.
        elif P == "PP":
            if fpsys.state.samepogs:
                key = "PPs"
            else:
                key = "PPr" if T.isInstalled() else "PPw"
        # Some kind of error
        else:
            print _("FontView state error: Pattern is \"{}\"").format(P)
            raise SystemExit

        ## ..and use it to fetch from dict self.lbl_d
        d = self.lbl_d[key]

        # Little func to replace substrings.
        def rep(s):
            if "VIEW" in s: s = s.format(VIEW=V.label())
            if "TARGET" in s: s = s.format(TARGET=T.label())
            return s

        lab = rep(d['lab'])

        ## Do we add extra text about recursing?
        rtest = d.get('rtest', None)
        if rtest:
            lab = lab.format(RT=rtest())  # yes

        ## using dict n_a_r_s
        nars = d['nars']

        fpsys.state.cantick = nars['cantick']
        fpsys.state.action = nars['action']
        self.TICKMAP = nars['tmap']

        ## Enable/Disable the Purge menu item
        ## Switch it off, then: if the view is a Pog
        ## and it's *not* installed, we can switch it on.
        ## (Because you can't purge an installed font.)
        ## This has nothing to do with whatever target
        ## may be selected.
        ps.pub(toggle_purge_menu_item, False)
        if VC == "P" and not V.isInstalled():
            ps.pub(toggle_purge_menu_item, True)

        self.buttMainLastLabel = rep(nars['btext'])

        self.main_font_info_label.SetLabel(lab)
        self.main_font_info_label.Show()

        i = nars['info']
        t = d.get('tip', "")
        st = rep(u"{} {}".format(i, t))
        self.status_text.SetLabel(st)

        self.ToggleMainButton()

        fpsys.markInactive()
        self.filterAndPageThenCallCreateFitmaps()
Exemple #11
0
class FontViewPanel(wx.Panel):
    """
    Standalone visual control to select fonts.
    The Panel that holds the ScrolledFontView control
    as well as the buttons etc. below and the text above.
    """
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, id=-1)
        self.firstrun = True

        self.pageindex = 1  # I start here
        self.total_number_of_pages = 0

        self.filter = ""

        self.TICKMAP = None
        self._TICK = fpwx.wxbmp('tick')
        self._CROSS = fpwx.wxbmp('cross')

        #Sept 2009
        ## Bitmaps to be used in the Fitmap drawing.
        ## Fetched from there as dict items. It got weird.
        self.SEGFAULT = fpwx.wxbmp('font_segfault')
        self.NO_DRAW = fpwx.wxbmp('font_cannot_draw')
        self.NOT_FOUND = fpwx.wxbmp('font_not_found')
        self.INFO_ITEM = fpwx.wxbmp('font_info_item')
        self.TICKSMALL = fpwx.wxbmp('ticksmall')
        self.BUTTON_CHARMAP = fpwx.wxbmp('button_charmap')
        self.BUTTON_CHARMAP_OVER = fpwx.wxbmp('button_charmap_over')

        ## --
        ## Dicts for use in state
        ##
        self._setup_state_dicts()

        ##
        ## START GUI
        ## ===
        #icon_open_folder = fpwx.wxbmp("icon_open_folder")
        #icon_pog = fpwx.wxbmp("pog16x16")
        #icon_pog_installed = fpwx.wxbmp("pog16x16.installed")

        ## Sizer: to hold all the others
        main_view_sizer = wx.BoxSizer(wx.VERTICAL)

        ## Sizer: Icon and Main Label
        icon_and_text_sizer = wx.BoxSizer(wx.HORIZONTAL)

        ## Sizer: Filter and Pager controls
        filter_and_pager_sizer = wx.BoxSizer(wx.HORIZONTAL)

        ## Icon
        view_icon = fpwx.icon(self, 'icon_viewing')

        # Main heading
        self.main_font_info_label = fpwx.h1(self,
                                            u"..",
                                            ellip=wx.ST_ELLIPSIZE_END,
                                            Layout_func=self.Layout)

        icon_and_text_sizer.Add(view_icon,
                                0,
                                wx.EXPAND | wx.ALIGN_CENTER_HORIZONTAL
                                | wx.RIGHT,
                                border=4)

        icon_and_text_sizer.Add(self.main_font_info_label,
                                1,
                                wx.EXPAND | wx.TOP
                                | wx.ALIGN_CENTER_HORIZONTAL,
                                border=6)

        ## The status label
        self.status_text = fpwx.label(self,
                                      u"Subinfo",
                                      ellip=wx.ST_ELLIPSIZE_END,
                                      Layout_func=self.Layout)

        ## Quick search Bold Italic Regular buttons
        ## It occurs to me that these are English words...
        ## Do fonts contain i18n on styles?
        ## See: https://fontforge.github.io/fontstyles.html
        idBold = wx.NewId()
        idItalic = wx.NewId()
        self.idRegular = wx.NewId()
        self.BIR = {
            idBold: {
                'style': "bold",
                'truth': False,
                'instance': None
            },
            idItalic: {
                'style': "italic",
                'truth': False,
                'instance': None
            },
            self.idRegular: {
                'style': "regular",
                'truth': False,
                'instance': None
            }
        }
        toggle_sizer = wx.BoxSizer(wx.HORIZONTAL)
        for idy, dic in self.BIR.iteritems():
            bBIR = wx.ToggleButton(self,
                                   idy,
                                   size=(32, -1),
                                   style=wx.NO_BORDER)
            #Remarked label to show icons instead, label=dic['label'])
            bBIR.Bind(wx.EVT_TOGGLEBUTTON, self.onBIR)

            bmp = fpwx.wxbmp('icon_{}'.format(dic['style']))
            bBIR.SetBitmap(bmp)

            bBIR.SetToolTipString(_("Filter {} fonts").format(dic['style']))

            self.BIR[idy]['instance'] = bBIR

            toggle_sizer.Add(bBIR, 1, wx.EXPAND)

        filter_and_pager_sizer.Add(toggle_sizer, 1, wx.EXPAND)

        # Search box - has two callbacks
        self.search_filter = SearchFilter(
            self,
            search_func=self.do_search,
            cancel_func=self.on_clear_button_click)

        self.last_filter_string = ""

        filter_and_pager_sizer.Add( self.search_filter, 5,
                wx.ALIGN_LEFT | wx.EXPAND \
                | wx.RIGHT, border = 6)

        ## The pager pulldown
        pager_label = fpwx.label(self, _(u"Page:"))
        self.pager_combo = wx.ComboBox(self,
                                       -1,
                                       value="1",
                                       choices=["busy"],
                                       style=wx.CB_DROPDOWN
                                       | wx.TE_PROCESS_ENTER)

        self.pager_combo.Bind(wx.EVT_COMBOBOX, self.onPagechoiceClick)
        self.pager_combo.Bind(wx.EVT_TEXT_ENTER, self.onPagerChoiceTextEnter)

        filter_and_pager_sizer.Add(pager_label,
                                   0,
                                   wx.ALIGN_RIGHT | wx.ALIGN_CENTER_VERTICAL
                                   | wx.RIGHT,
                                   border=6)
        filter_and_pager_sizer.Add(self.pager_combo, 1)  #, wx.ALIGN_RIGHT )

        ## The SCROLLED FONT VIEW panel:
        self.scrolledFontView = ScrolledFontView(self)

        ## Sizer: for buttons prev, main, next
        bottom_buttons_sizer = wx.BoxSizer(wx.HORIZONTAL)

        #July 2016
        #=========
        # The stock icon on the button was not showing under gtk3.
        # This stock button has not been translated into Afrikaans yet. (Dec 2007)
        # I can't tell you how this fkuced me around!
        # July 2016 - remarked : self.next_button = wx.Button(self, wx.ID_FORWARD)
        # I have switched to a bitmapbutton. I hope this works...
        ###
        # For future:
        # example = wx.BitmapButton(self, -1, fpwx.wxbmp( "xxx" ),
        #  style = wx.NO_BORDER)

        # Previous button
        #self.previous_button = wx.BitmapButton( self, wx.ID_BACKWARD,
        #        wx.ArtProvider.GetBitmap(
        #            wx.ART_GO_BACK, wx.ART_BUTTON, (32,32) ))

        self.previous_button = wx.BitmapButton(self, wx.ID_BACKWARD,
                                               fpwx.wxbmp('icon_prev_page'))
        # Main button
        self.button_main = wx.Button(self, label=" ")
        self.buttMainLastLabel = " "

        # Next button
        #self.next_button = wx.BitmapButton( self, wx.ID_FORWARD,
        #        wx.ArtProvider.GetBitmap(
        #            wx.ART_GO_FORWARD, wx.ART_BUTTON, (32,32) ))

        self.next_button = wx.BitmapButton(self, wx.ID_FORWARD,
                                           fpwx.wxbmp('icon_next_page'))
        self.previous_button.Enable(False)  # Starts out disabled

        bottom_buttons_sizer.Add(self.previous_button,
                                 0,
                                 wx.EXPAND | wx.RIGHT,
                                 border=8)

        bottom_buttons_sizer.Add(self.button_main,
                                 1,
                                 wx.EXPAND | wx.RIGHT,
                                 border=8)

        bottom_buttons_sizer.Add(self.next_button, 0, wx.EXPAND)

        ## Start at the top: the icon and label
        main_view_sizer.Add(icon_and_text_sizer, 0, wx.EXPAND)

        ## Sub label
        main_view_sizer.Add(self.status_text, 0, wx.EXPAND | wx.TOP, border=4)

        ## Fill the Choice and Filter
        main_view_sizer.Add(filter_and_pager_sizer,
                            0,
                            wx.EXPAND | wx.TOP,
                            border=8)

        ## Fill the SIZER FOR THE SCROLLED FONT VIEW
        main_view_sizer.Add(self.scrolledFontView,
                            1,
                            wx.EXPAND | wx.TOP,
                            border=8)

        ## Fill the bottom buttons
        main_view_sizer.Add(bottom_buttons_sizer,
                            0,
                            wx.EXPAND | wx.TOP,
                            border=10)

        ## Do the voodoo thang
        self.SetSizer(main_view_sizer)

        ## This Fit is NB. It sets the width
        ## for all panels to come.
        ## Remove it and the various AutoWrapStaticText
        ## objects fail hard.
        self.Fit()

        ## Bind events
        self.previous_button.Bind(wx.EVT_BUTTON, self.navClick)
        self.next_button.Bind(wx.EVT_BUTTON, self.navClick)
        self.Bind(wx.EVT_BUTTON, self.onMainClick,
                  self.button_main)  #.GetId() )

        ## Advertise some local functions:
        ps.sub(left_or_right_key_pressed,
               self.OnLeftOrRightKey)  ##DND: class FontViewPanel

        ps.sub(toggle_main_button,
               self.ToggleMainButton)  ##DND: Called in gui_Fitmap
        ps.sub(update_font_view,
               self.MainFontViewUpdate)  ##DND: class FontViewPanel
        ps.sub(reset_to_page_one,
               self.ResetToPageOne)  ##DND: class FontViewPanel

    # Tried to implement wrapping on some of the labels.
    # It flickers and fails. F**k it.
    #def on_evt_size(self,e):
    #w = e.GetSize()[0]
    #w = max(w+5,200)
    #self.status_text.Wrap(w)
    #   e.Skip()

    def on_clear_button_click(self):  #, event ):
        self.filter = ""

        # Clear the BIR toggle buttons
        self.setAllBIRFalse()

        ## Now command a change of the view.
        ## First, return user to page 1:
        self.pageindex = 1
        self.filterAndPageThenCallCreateFitmaps()
        # A GTK bug demands this move. Restore the ESC key func.
        self.button_main.SetFocus()

    def setOneBIR(self, idy, truth):
        self.BIR[idy]['truth'] = truth
        self.BIR[idy]['instance'].SetValue(truth)

    def setAllBIRFalse(self):
        for idy in self.BIR.keys():
            self.setOneBIR(idy, False)

    def onBIR(self, e):
        idy = e.GetId()
        toggstate = self.BIR[idy]['instance'].GetValue()

        self.BIR[idy]['truth'] = toggstate

        ss = ""
        if self.BIR[idy]['style'] == "regular":
            # only if this is toggle on, do we want
            # action anything:
            if toggstate is True:
                # can't have regular with bold/italic
                self.setAllBIRFalse()  # switch all off
                self.setOneBIR(idy, True)
                ss = "regular|normal"
        else:
            self.setOneBIR(self.idRegular, False)
            for idy, dic in self.BIR.iteritems():
                # Builds an AND regex (a space is "AND")
                if dic['truth']: ss += "{}{}".format(dic['style'], " ")
            ss = ss[:-1]
        # Go alter the search text box
        self.search_filter.set_BIR(ss)

        # Start the process
        self.startSearch(ss)

    def do_search(self, sstring):
        """
        SearchFilter control will call this with
        sstring being the filter term.
        """
        self.startSearch(sstring)
        self.button_main.SetFocus()
        return True  # to store in history

    def startSearch(self, terms):
        self.filter = terms
        ## First, return user to page 1:
        self.pageindex = 1

        ## Now command a change of the view.
        self.filterAndPageThenCallCreateFitmaps()

    def filterAndPageThenCallCreateFitmaps(self):
        """
        Figure out what list of fonts to draw, divide them into pages,
        then go make Fitmaps out of them.
        """

        self.total_number_of_pages = 1  # A default

        ## Is there anything there to view?
        if len(fpsys.state.viewobject) > 0:

            ## JUNE 2009 : Changes made

            ## If the filter string changed from last time, signal so.
            filter_changed = False
            if self.filter != self.last_filter_string: filter_changed = True
            self.last_filter_string = self.filter

            ## If the filter did change OR we have a blank
            ## filteredViewObject, then make a new one.
            if not fpsys.state.filteredViewObject or filter_changed:
                fpsys.state.filteredViewObject = fontyfilter.doFilter(
                    self.filter)  # Uses the external module to filter.

            ## STEP 2 : Figure out how many pages we have to display
            current_page = self.pageindex - 1
            num_in_one_page = fpsys.config.numinpage
            total_num_fonts = len(fpsys.state.filteredViewObject)

            ## Many thanks to Michael Hoeft for this fix! I suck at math :)
            # I miss the right words to explain this step, therefore an example:
            #  23 / 10 = 2
            #  23 % 10 = 3 > modulo > bool(3) = True = 1
            #  -----------------------------------------
            #  2 + 1 = 3 >  3 pages
            #
            #  40 / 10 = 4
            #  40 % 10 = 0 > modulo > bool(0) = False = 0
            # ------------------------------------------
            #  4 + 0 = 4 > 4 pages
            self.total_number_of_pages = (total_num_fonts / num_in_one_page) \
                    + bool(total_num_fonts % num_in_one_page)

            #leaf thru the pages to the one we are on now.
            start = current_page * num_in_one_page
            fin = start + num_in_one_page
            # Make sure we don't overshoot.
            if fin > len(fpsys.state.filteredViewObject):
                fin = len(fpsys.state.filteredViewObject)

            ## Extract a single page of fonts to display
            sublist = fpsys.state.filteredViewObject[start:fin]

            ## Empty the choice control.
            self.pager_combo.Clear()

            ## Now refill it
            [
                self.pager_combo.Append(str(n))
                for n in xrange(1, self.total_number_of_pages + 1)
            ]
            self.pager_combo.SetSelection(self.pageindex - 1)
            #self.choiceSlider.SetRange(1,self.total_number_of_pages+1)

        ## The viewobject is empty anyway.
        else:
            sublist = []

        if self.total_number_of_pages == 1:
            self.pager_combo.Enable(False)
        else:
            self.pager_combo.Enable(True)

        # Tell my child to draw the fonts
        self.scrolledFontView.MinimalCreateFitmaps(sublist)

        self.EnableDisablePrevNext()

    def _setup_state_dicts(self):
        """
        These dicts are used in MainFontViewUpdate.
        They hold the variables and such for various
        states of the app i.t.o Source/View and Target.
        """
        # Some common strings
        nadatd = _("There's nothing much to do.")
        ntd = _("Choose some fonts")
        # The "nothing add remove samepogs" dict
        # Will be used in the main dict below.
        n_a_r_s = {
            'n': {  #Nothing
                'btext': ntd,
                'action': "NOTHING_TO_DO",
                'info': nadatd,
                'cantick': False,
                'tmap': self._TICK  #default, but is not drawn. 
            },
            's': {  #Same
                'btext': ntd,
                'action': "NOTHING_TO_DO",
                'info': nadatd,
                'cantick': False,
                'tmap': self._TICK
            },
            '-': {  #Remove
                'btext': _("Remove fonts from {VIEW}"),
                'info': _("You can remove fonts from this source Pog."),
                'action': "REMOVE",
                'cantick': True,
                'tmap': self._CROSS
            },
            '+': {  #Append
                'btext':
                _("Put fonts into {TARGET}"),
                'info':
                _("You can append fonts to the active target Pog \"{TARGET}\"."
                  ),
                'action':
                "APPEND",
                'cantick':
                True,
                'tmap':
                self._TICK
            }
        }

        # A way to test for recurse flag later
        recurse_test = lambda: _(" (and all sub-folders.)") \
                               if fpsys.config.recurseFolders else ""

        # Some common strings
        vF = _("Viewing source Folder \"{VIEW}\"{{RT}}")
        vP = _("Viewing source Pog \"{VIEW}\"")
        choose_source = _("Choose a Source Pog or Folder.")
        nochangetarget = _("The target Pog \"{TARGET}\" is installed. "\
                        "It can't be changed.")

        # The main "label" dict.
        # See remarks in MainFontViewUpdate for details.
        self.lbl_d = {
          ## Empty to Nothing
          'EN' : {
            'lab': _("There are no fonts in here."),
            'tip': choose_source,
           'nars': n_a_r_s['n']
               },

          ## Empty to Pog
          'EP' : {
            'lab': _("Source is empty. The active target Pog is \"{TARGET}\""),
            'tip': choose_source,
           'nars': n_a_r_s['n']
               },

          ## Folder to Nothing
          'FN' : {
            'lab': vF,
           'nars': n_a_r_s['n'],
          'rtest': recurse_test
               },

          ## Pog to Nothing
          'PrN': {
            'lab': _("Viewing (installed Pog) \"{VIEW}\""),
            'tip': _("You can't change an installed Pog."),
           'nars': n_a_r_s['n']
               },
          'PwN': { # '-' Remove from source pog
            'lab': _("Viewing (editable Pog) \"{VIEW}\""),
            'tip': _("There is no active target."),
           'nars': n_a_r_s['-']
               },

          ## Folder to Pog
          'FPr': {
            'lab': vF,
            'tip': nochangetarget,
           'nars': n_a_r_s['n'],
          'rtest': recurse_test,
               },
          'FPw': { # Add to target Pog
            'lab': vF,
           'nars': n_a_r_s['+'],
          'rtest': recurse_test,
              },

          ## Pog to Pog
          'PPr': {
            'lab': vP,
            'tip': nochangetarget,
           'nars': n_a_r_s['n'],
              },
          'PPs': {
            'lab':  _("Source and Target \"{VIEW}\" are the same."),
            'tip': _("Clear the target, or choose another Pog."),
           'nars': n_a_r_s['s'],
              },
          'PPw': { # Add to target Pog
            'lab': vP,
           'nars': n_a_r_s['+'],
              }
          }

    def MainFontViewUpdate(self):
        """
        Vital routine - the heart if the app.

        This decides what to do based on what has been selected.
        It draws the controls and the fonts as appropriate.
        It also sets flags in fpsys.state
        """

        ## If any DismissablePanels are open, hide them:
        ps.pub(ensure_fontview_shown)

        ## Get shorter vars to use.
        V = fpsys.state.viewobject
        T = fpsys.state.targetobject

        VC = fpsys.state.viewpattern  # View Char
        TC = fpsys.state.targetpattern  # Target Char

        P = VC + TC  # a two-char flag

        ## Okay, let's make a key:..

        ## [S][rw][T][rws] <-- key's basic shape
        ## Where S is Source, T is Target:
        ##  E == Empty View/Source - no fonts in chosen Source.
        ##  N == Empty Target - no fonts.
        ##  P is Pog
        ##  F is Folder
        ## And rw:
        ## r is read (i.e. only can view)
        ## w is write (i.e. remove or append)
        ## s is same (S/T pogs are the same)
        ## Example:
        ## PrN -> Source pog+read. No target pog.
        ##     i.e: We are viewing a pog that is installed
        ##     (no write.)
        ## FPw -> Source folder. Target pog+write
        ##     i.e. We are viewing a folder and have a Pog
        ##     which is *not* installed, so can be 'written'
        ##     i.e. have fonts appended.

        # EN -> EN (Empty source, No target)
        # EP -> EP (Empty source, Pog target (weird) )
        # FN -> FN (Folder source, No target)
        if P in ('EN', 'EP', 'FN'):
            key = P

        # PN -> PrN or PwN
        # Pog source, No target.
        # Because 1) source is a Pog
        #     and 2) there's no target,
        # the Pog can be:
        #  r = view it only (i.e. it's installed)
        #  w = remove fonts
        elif P == "PN":
            key = "PrN" if V.isInstalled() else "PwN"

        # FP -> FPr or FPw
        # Folder source, Pog target. Target r or w.
        # Similar logic. If target pog is installed
        # it can't be added-to, i.e. it's 'r' only.
        # else it can be 'w'
        elif P == "FP":
            key = "FPr" if T.isInstalled() else "FPw"

        # PP -> PPr or PPw or PPs
        # Target pog is either 'r' or 'w' or ...
        # Target pog 's' means source and target are same.
        elif P == "PP":
            if fpsys.state.samepogs:
                key = "PPs"
            else:
                key = "PPr" if T.isInstalled() else "PPw"
        # Some kind of error
        else:
            print _("FontView state error: Pattern is \"{}\"").format(P)
            raise SystemExit

        ## ..and use it to fetch from dict self.lbl_d
        d = self.lbl_d[key]

        # Little func to replace substrings.
        def rep(s):
            if "VIEW" in s: s = s.format(VIEW=V.label())
            if "TARGET" in s: s = s.format(TARGET=T.label())
            return s

        lab = rep(d['lab'])

        ## Do we add extra text about recursing?
        rtest = d.get('rtest', None)
        if rtest:
            lab = lab.format(RT=rtest())  # yes

        ## using dict n_a_r_s
        nars = d['nars']

        fpsys.state.cantick = nars['cantick']
        fpsys.state.action = nars['action']
        self.TICKMAP = nars['tmap']

        ## Enable/Disable the Purge menu item
        ## Switch it off, then: if the view is a Pog
        ## and it's *not* installed, we can switch it on.
        ## (Because you can't purge an installed font.)
        ## This has nothing to do with whatever target
        ## may be selected.
        ps.pub(toggle_purge_menu_item, False)
        if VC == "P" and not V.isInstalled():
            ps.pub(toggle_purge_menu_item, True)

        self.buttMainLastLabel = rep(nars['btext'])

        self.main_font_info_label.SetLabel(lab)
        self.main_font_info_label.Show()

        i = nars['info']
        t = d.get('tip', "")
        st = rep(u"{} {}".format(i, t))
        self.status_text.SetLabel(st)

        self.ToggleMainButton()

        fpsys.markInactive()
        self.filterAndPageThenCallCreateFitmaps()

    def onMainClick(self, evt):
        """
        Removes fonts, or Appends fonts. Depends on situation in fpsys.state
        """
        #Saved by Robin Dunn, once again ! ! !
        xPos, yPos = self.scrolledFontView.GetViewStart()
        wx.BeginBusyCursor()
        doupdate = False

        ## Let's determine what kind of thing to do:
        if fpsys.state.action == "REMOVE":
            ## We have a pog in viewobject and we must remove the
            ## selected fonts from it.
            vo = fpsys.state.viewobject
            victims = []
            dowrite = False
            for fi in vo:
                if fi.ticked:
                    victims.append(fi)  #Put it into another list
                    dowrite = True
            for fi in victims:
                vo.remove(fi)  #Now remove it from the vo
            del victims

            if dowrite:
                fpsys.flushTicks()
                bug = False
                try:
                    vo.write()
                except (fontybugs.PogWriteError), e:
                    bug = True
                    ps.pub(show_error, unicode(e))

                doupdate = True

                if not bug:
                    ps.pub(print_to_status_bar,
                           _("Selected fonts have been removed."))
                else:
                    ps.pub(print_to_status_bar,_(
                        "There was an error writing the pog "\
                        "to disk. Nothing has been done."))

        ## APPEND - Copy font to a pog.
        if fpsys.state.action == "APPEND":
            ## We must append the fonts to the Pog
            vo = fpsys.state.viewobject
            to = fpsys.state.targetobject
            # pointless print:
            #print _("Copying fonts from {source} to {target}").format(**{
            #        "source":vo.label(), "target":to.label()})
            dowrite = False
            for fi in vo:
                if fi.ticked:
                    to.append(fi)
                    dowrite = True
            if dowrite:
                #Ensure we have no more ticks after a succ. xfer.
                fpsys.flushTicks()
                bug = False
                try:
                    to.write()
                except (fontybugs.PogWriteError), e:
                    bug = True
                    ps.pub(show_error, unicode(e))

                doupdate = True

                if not bug:
                    ps.pub(
                        print_to_status_bar,
                        _("Selected fonts are now in \"{}\".").format(
                            to.label()))
                else:
                    ps.pub(print_to_status_bar,_(
                        "There was an error writing the pog to disk. " \
                        "Nothing has been done"))
class NoteBook(wx.Notebook):
    """
    THIS IS THE VIEW or SOURCE of fonts.
    Has two tabs - Folders and Pogs
    """
    def __init__(self, parent, name="notebook_not_named"):
        wx.Notebook.__init__(self, parent, style=wx.NB_TOP, name = name)
        self.imlist = wx.ImageList(16, 16)

        pan1 = wx.Panel(self)

        ## THE DIR CONTROL
        self.dircontrol = DirControl(pan1)

        # Get a ref to the dircontrol.
        self.tree = self.dircontrol.GetTreeCtrl()

        ## Add them to a sizer
        box = wx.BoxSizer(wx.VERTICAL)
        box.Add( self.dircontrol,1, wx.EXPAND )
        pan1.SetSizer(box)
        box.Layout()

        self.pogindexselected = 0

        ## The SOURCE POG control
        pan2 = wx.Panel(self)
        page = 0
        s = None
        if fpsys.state.viewpattern  == "P":
            s = fpsys.state.viewobject.name
            if s == "EMPTY": s= None #Very first run, the view will be an EMPTY object.
            page = 1
        self.ctrlPogSource = PogChooser(pan2, whoami="SOURCEPOG", select = s)


        ps.sub( source_pog_has_been_selected, self.OnViewPogClick) ##DND: class NoteBook
        ps.sub( select_no_view_pog, self.SelectNoView) ##DND: class NoteBook
        ps.sub( add_pog_item_to_source, self.AddItem ) #DND: class NoteBook
        ps.sub( remove_pog_item_from_source, self.RemoveItem ) #DND: class NoteBook


        ## Dud tree events, causing bad behaviour:
        ## EVT_LIST_ITEM_SELECTED
        ## EVT_LEFT_UP

        ## Bind to another event solve the problem of 
        ##  EVT_LEFT_UP firing when the little
        ##  open-branch/tree arrow was pressed.
        ##  5.3.2009 Michael Hoeft
        ## Nov 2017: Also subscribe this for use in wxgui - since 
        ## I moved the recurseFolders into there.
        ps.sub( fake_click_the_source_dir_control, self.__onDirCtrlClick )
        self.tree.Bind(wx.EVT_TREE_SEL_CHANGED, self.__onDirCtrlClick)

        ## Had a context menu, but not using it.
        #self.tree.Bind(wx.EVT_CONTEXT_MENU, self.OnContextMenu)

        box2 = wx.BoxSizer(wx.HORIZONTAL)
        box2.Add(self.ctrlPogSource,1,wx.EXPAND)
        pan2.SetSizer(box2)
        box2.Layout()

        self.AddPage(pan1, _("Source Folders"))
        self.AddPage(pan2, _("Source Pogs"))

        # sadly, the artprovider icons suck, and I can't get access 
        # to the "stock items" either. F**k it. 
        source_folder_icon = self.imlist.Add(
                fpwx.wxbmp('icon_source_folder_16x16') )
        source_pog_icon = self.imlist.Add(
                fpwx.wxbmp('icon_source_pog_16x16') )

        self.AssignImageList(self.imlist)
        self.SetPageImage(0, source_folder_icon)
        self.SetPageImage(1, source_pog_icon)

        self.SetSelection(page)

        # Dec 2017: Remarked this Bind. See notes in old handler
        #self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, 
        # self.onPageChanged) # Bind page changed event

        ## If the app is started with a Folder as the Source, then
        ## check if we must recurse. If so, fake a click to kick that off.
        ## Sept 2017
        if fpsys.state.viewpattern  == "F":
            self.__onDirCtrlClick() # Fake an event


    def onPageChanged(self, e):
        """
        The notebook page change handler.
        Remarked the Bind Dec 2017.
        
        A click on the notebook tabs should not make assumptions
        about what source to select.

        By ignoring this, the new eye icon remains on the last 
        selected directory.

        It's not perfect, because coming back to the dir control
        shows what was selected before, but you can't click on the
        same selection and get a result. You must click-off and 
        click-on to get the view to update.
        
        I moved the UnselectAll call into OnViewPogClick so that
        when you click on an actual source Pog, the tree control
        now moves out of play.

        I leave this code for the future.
        """
        self.ctrlPogSource.ClearLastIndex()
        if self.GetSelection() == 0: # The dircontrol
            #pass
            ## I want to force the dir control to clear the selection.
            ## Reason: When you return to this control (from Pog page),
            ## the selection from last visit is still there. 
            ## Clicking on it again does NOT UPDATE the font view. 
            ## This is wierd. So, clearing the selection makes it moot.

            ## This actually works:
            # wx.CallAfter( self.__onDirCtrlClick)
            # However.. I think it's weird.
            # When you click a tab in the notebook, it should
            # not make assumptions about what you mean.
            self.tree.UnselectAll() # Found this method in the wxpython book.


    def __onDirCtrlClick(self, evt = None):
        if evt:
            # I want this event to eventually arrive in
            # the Atree class; thus Skip()
            # (See gui_DirChooser.py)
            evt.Skip() # Happens when this handler finishes.

        wx.BeginBusyCursor() #Thanks to Suzuki Alex on the wxpython list!
        p = self.dircontrol.GetPath()

        try:
            fpsys.instantiateViewFolder( p, fpsys.config.recurseFolders )
            fpsys.config.lastdir = p
        except fontybugs.FolderHasNoFonts, err:
            pass # update_font_view handles this with a std message.

        ps.pub(reset_to_page_one)# reset before updating!  
        ps.pub(update_font_view)

        wx.EndBusyCursor()
        wx.CallAfter( self.SetFocus )
Exemple #13
0
 def onMiddleClick(self, event):
     ps.pub( open_settings_panel)