= How to create a Tip of the day frame (Phoenix) =
'''Keywords :''' Tip of the Day, CreateFileTipProvider, ShowTip, TipProvider, Dialog, Option.

<<TableOfContents>>

--------
= Introduction =
"Tip of the day" is easily implemented with the wxCreateFileTipProvider function and a text file full of tips.

Your application will need:

 * Some sort of persistence to remember whether tips are being shown and which tip will be shown next. For this recipe, I'm just referring to {{{self.Persist}}}, but I am not illustrating how {{{self.Persist}}} is created, saved, or restored.

You should also include:

 * A settings panel that allows the user to turn the tips on/off, or a menu option for showing a tip of the day. Otherwise, if the user turns the tips off, they will not be able to turn them back on again!

--------
= The Recipe =
First, create a text file ({{{tips.txt}}}) with helpful tips in it. Lines that begin with a "#" will be treated as comments:

{{{
# Dental hygene tips:
Brush your teeth three times a day.
Floss every day.
An apple a day keeps the doctor away.
}}}
In your frame's intialization, create a tip provider:

{{{#!python
self.TipOfTheDay = wx.CreateFileTipProvider("tips.txt", self.Persist.TipOfTheDayIndex)
if self.Persist.ShowTotD:
    wx.CallAfter(self.ShowTipOfTheDay)
}}}
Note that I'm doing a {{{wx.CallAfter}}} so that the initialization process doesn't grind to a halt while waiting for the user to dismiss the tip.

The {{{ShowTipOfTheDay}}} function is:

{{{#!python
def ShowTipOfTheDay(self):
    self.Persist.ShowTotD = wx.ShowTip(self, self.TipOfTheDay, self.Persist.ShowTotD)
}}}
Finally, when my application is shutting down, I recapture the current tip number so that the tips will pick up from where they left off on the next run.

{{{#!python
self.Persist.TipOfTheDayIndex = self.TipOfTheDay.CurrentTip
}}}
That {{{CurrentTip}}} member doesn't appear to be documented in the help files, but it does seem to do the trick.

--------
= Demonstrating : =
__'''''Tested''' py3.x, wx4.x and Win10. ''__

Are you ready to use some samples ? ;)

Test, modify, correct, complete, improve and share your discoveries ! (!)

--------
== Here's a complete example of using ==
{{attachment:img_sample_one.png}}

{{{#!python
# sample_one.py

import sys
import os
import wx
from wx.adv import CreateFileTipProvider
from wx.adv import ShowTip
from wx.adv import TipProvider

# class MyTipOption
# class MyFrame
# class MyApp

app_dir = os.path.split(os.path.abspath(sys.argv[0]))[0]
config_file = os.path.join(app_dir, "options.cfg")

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

class MyTipOption(wx.Dialog):
     def __init__(self, parent):
          wx.Dialog.__init__(self, parent, -1, title="Option tips")

          self.Bind(wx.EVT_CLOSE, self.on_close_window)

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

          config = GetConfig()
          self.checkBox = wx.CheckBox(self, -1,
                                      label="Show tips at start up",
                                      pos=(20, 20))
          self.checkBox.SetValue(config.ReadInt("ShowTips", 0))
          content = self.checkBox.GetValue()
          print("CheckBox = %s" % (content))

          self.btnClose = wx.Button(self, -1,
                                    label="&Close",
                                    pos=(20, 120),
                                    size=(100, 30))

          self.checkBox.Bind(wx.EVT_CHECKBOX, self.on_check_box)
          self.Bind(wx.EVT_BUTTON, self.on_close_btn, self.btnClose)

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

          self.CentreOnParent(wx.BOTH)

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

          self.btnClose = self.ShowModal()
          self.Close()

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

     def on_check_box(self, event):
          config = GetConfig()
          config.WriteInt("ShowTips", self.checkBox.GetValue())
          content = self.checkBox.GetValue()
          print("CheckBox = %s" % (content))

     def on_close_btn(self, event):
          self.Close(True)

     def on_close_window(self, event):
          self.Destroy()

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

class MyFrame(wx.Frame):
     def __init__(self, parent, id, title):
          wx.Frame.__init__(self, parent, -1, title)

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

          frameicon = wx.Icon("Icons/wxWidgets.ico")
          self.SetIcon(frameicon)

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

          self.Bind(wx.EVT_CLOSE, self.on_close_window)

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

          self.panel = wx.Panel(self, -1)

          self.btnTip = wx.Button(self.panel, -1,
                                  label="Show &tip setting dialog",
                                  pos=(20, 20),
                                  size=(230, 30))
          self.btnClose = wx.Button(self.panel, -1,
                                    label="&Quit",
                                    pos=(20, 100),
                                    size=(100, 30))

          self.Bind(wx.EVT_BUTTON, self.on_tip_btn, self.btnTip)
          self.Bind(wx.EVT_BUTTON, self.on_close_btn, self.btnClose)

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

          # Simplified init method
          self.create_menu_bar()

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

          self.CenterOnScreen()

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

     def create_menu_bar(self):
          menuBar = wx.MenuBar()

          menuFile = wx.Menu(style=wx.MENU_TEAROFF)
          item = wx.MenuItem(menuFile, -1,
                             text="&Quit\tCtrl+Q",
                             helpString="Quit application.")
          menuFile.Append(item)
          self.Bind(wx.EVT_MENU, self.on_close_btn, item)

          menuOption = wx.Menu(style=wx.MENU_TEAROFF)
          item = wx.MenuItem(menuOption, -1,
                             text="&Tip\tCtrl+K",
                             helpString="Show or hide tip at start up.")
          menuOption.Append(item)
          self.Bind(wx.EVT_MENU, self.on_tip_btn, item)

          menuBar.Append(menuFile, title="&File")
          menuBar.Append(menuOption, title="&Option")
          self.SetMenuBar(menuBar)

     def show_tip(self):
          config = GetConfig()

          # Tip status (show or hide)
          showTip = config.ReadInt("ShowTips", 1)
          if showTip == 1 :
               print("Show tip = %s" % (True))
          elif showTip == 0 :
               print("Show tip = %s" % (False))

          index = config.ReadInt("TipIndex", 0)
          print("Index = %s" % (index))


          if showTip:
              tipProvider = CreateFileTipProvider("tips.txt", index)
              showTip = ShowTip(self, tipProvider)
              index = tipProvider.GetCurrentTip()

              config.WriteInt("ShowTips", showTip)
              config.WriteInt("TipIndex", index)

     def on_tip_btn(self, event):
          self.tip = MyTipOption(self)

     def on_close_btn(self, event):
          self.Close(True)

     def on_close_window(self, event):
          self.Destroy()

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

class MyApp(wx.App):
     def OnInit(self):
          self.SetAppName("Test_Tip")

          frame = MyFrame(None, -1, "Test show tip at start up")
          frame.Show(True)
          self.SetTopWindow(frame)

          if os.path.exists("tips.txt"):
              wx.CallAfter(frame.show_tip)

          return True

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

def GetConfig():
     config = wx.FileConfig(appName="Test_Tip",
                            localFilename=config_file)
     return config

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

if __name__ == "__main__":
     app = MyApp(False)
     app.MainLoop()
}}}
--------
== How change the widget text and internationalization support (i18n) ==
{{attachment:img_sample_two.png}}

{{{#!python
# sample_two.py

import sys
import os
import wx
from wx.adv import CreateFileTipProvider
from wx.adv import ShowTip
from wx.adv import TipProvider

# class MyTipOption
# class MyFrame
# class MyApp

app_dir = os.path.split(os.path.abspath(sys.argv[0]))[0]
config_file = os.path.join(app_dir, "options.cfg")

# Define a translation string
_ = wx.GetTranslation

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

class MyTipOption(wx.Dialog):
     def __init__(self, parent):
          wx.Dialog.__init__(self, parent, -1, title=_("Option"))

          self.Bind(wx.EVT_CLOSE, self.on_close_window)

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

          config = GetConfig()
          self.checkBox = wx.CheckBox(self, -1,
                                      label=_("Show tips at start up"),
                                      pos=(20, 20))
          self.checkBox.SetValue(config.ReadInt("ShowTips", 0))
          content = self.checkBox.GetValue()
          print("CheckBox = %s" % (content))

          self.text = wx.StaticText(self, -1,
                                    label=_("Language :"),
                                    pos=(20, 68))

          self.language = wx.Choice(self, -1,
                                    choices=[_("English"),
                                             _("French")],
                                    pos=(100, 65),
                                    size=(100, -1))

          self.btnClose = wx.Button(self, -1,
                                    label=_("&Close"),
                                    pos=(20, 120),
                                    size=(100, 30))

          self.checkBox.Bind(wx.EVT_CHECKBOX, self.on_check_box)
          self.Bind(wx.EVT_CHOICE, self.on_language)
          self.Bind(wx.EVT_BUTTON, self.on_close_btn, self.btnClose)

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

          self.CentreOnParent(wx.BOTH)

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

          self.btnClose = self.ShowModal()
          self.Close()

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

     def on_language(self, event):
          choice = self.language.GetSelection()
          print("Selection = %s" % (choice))

          config = GetConfig()
          if choice == 0:
               val = "LANGUAGE_ENGLISH"
          else:
               val = "LANGUAGE_FRENCH"
          print("Language = %s" % (val))
          config.Write("Language", val)

     def on_check_box(self, event):
          config = GetConfig()
          config.WriteInt("ShowTips", self.checkBox.GetValue())
          content = self.checkBox.GetValue()
          print("CheckBox = %s" % (content))

     def on_close_btn(self, event):
          self.Close(True)

     def on_close_window(self, event):
          self.Destroy()

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

class MyFrame(wx.Frame):
     def __init__(self, parent, id, title):
          wx.Frame.__init__(self, parent, -1, title)

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

          frameicon = wx.Icon("Icons/wxWidgets.ico")
          self.SetIcon(frameicon)

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

          self.Bind(wx.EVT_CLOSE, self.on_close_window)

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

          self.panel = wx.Panel(self, -1)

          self.btnTip = wx.Button(self.panel, -1,
                                  label=_("Show &tip setting dialog"),
                                  pos=(20, 20),
                                  size=(230, 30))
          self.btnClose = wx.Button(self.panel, -1,
                                    label=_("&Quit"),
                                    pos=(20, 100),
                                    size=(100, 30))

          self.Bind(wx.EVT_BUTTON, self.on_tip_btn, self.btnTip)
          self.Bind(wx.EVT_BUTTON, self.on_close_btn, self.btnClose)

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

          # Simplified init method
          self.create_menu_bar()

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

          self.CenterOnScreen()

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

     def create_menu_bar(self):
          menuBar = wx.MenuBar()

          menuFile = wx.Menu(style=wx.MENU_TEAROFF)
          item = wx.MenuItem(menuFile, -1,
                             text=_("&Quit\tCtrl+Q"),
                             helpString=_("Quit application."))
          menuFile.Append(item)
          self.Bind(wx.EVT_MENU, self.on_close_btn, item)

          menuOption = wx.Menu(style=wx.MENU_TEAROFF)
          item = wx.MenuItem(menuOption, -1,
                             text=_("&Setting\tCtrl+K"),
                             helpString=_("Setting language and tip."))
          menuOption.Append(item)
          self.Bind(wx.EVT_MENU, self.on_tip_btn, item)

          menuBar.Append(menuFile, title=_("&File"))
          menuBar.Append(menuOption, title=_("&Option"))
          self.SetMenuBar(menuBar)

     def show_tip(self):
          config = GetConfig()

          # Tip status (show or hide)
          showTip = config.ReadInt("ShowTips", 1)
          if showTip == 1 :
               print("Show tip = %s" % (True))
          elif showTip == 0 :
               print("Show tip = %s" % (False))

          index = config.ReadInt("TipIndex", 0)
          print("Index = %s" % (index))

          if showTip:
              tipProvider = CreateFileTipProvider("tips.txt", index)
              showTip = ShowTip(self, tipProvider)
              index = tipProvider.GetCurrentTip()

              config.WriteInt("ShowTips", showTip)
              config.WriteInt("TipIndex", index)

     def on_tip_btn(self, event):
          self.tip = MyTipOption(self)

     def on_close_btn(self, event):
          self.Close(True)

     def on_close_window(self, event):
          self.Destroy()

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

class MyApp(wx.App):
     def OnInit(self):
          self.SetAppName("Test_Tip_i18n")

          # Retrieve the user configuration language
          config = GetConfig()
          language = config.Read("Language", "LANGUAGE_DEFAULT")

          # Setup the locale
          self.locale = wx.Locale(getattr(wx, language))
          path = os.path.abspath("./locale") + os.path.sep
          self.locale.AddCatalogLookupPathPrefix(path)
          self.locale.AddCatalog(self.GetAppName())

          frame = MyFrame(None, -1, _("Test show tip at start up - i18n"))
          frame.Show(True)
          self.SetTopWindow(frame)

          if os.path.exists("tips.txt"):
              wx.CallAfter(frame.show_tip)

          return True

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

def GetConfig():
     config = wx.FileConfig(appName="Test_Tip_i18n",
                            localFilename=config_file)
     return config

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

if __name__ == "__main__":
     app = MyApp(False)
     app.MainLoop()
}}}
--------
= Download source =
[[attachment:source.zip]]

--------
= Additional Information =
For the non-ascii characters, save the text file with an utf-8 encoding.

For the translation or editing, you can use Poedit application.

It exist some version for Windows, Mac and Linux.

'''Link :'''

https://en.wikipedia.org/wiki/Poedit

https://fr.wikipedia.org/wiki/Poedit

https://wiki.wxpython.org/WikiTipOfTheDay

- - - - -

https://wiki.wxpython.org/TitleIndex

https://docs.wxpython.org/

--------
= Thanks to =
Robin Dunn, Cody Precord, the wxPython community...

Thanks also to all known contributors or anonymous that I forgot.

--------
= About this page =
Date (d/m/y) Person (bot)    Comments :

10/10/18 - Ecco (Created page for wxPython Phoenix).

--------
= Comments =
- blah, blah, blah....