HTML based hint component

Hello Folks,

I'm working on a HTML based hint component. Works this way:

HtmlHint(widget,"<img src=\"16/query\"> This is a test hint")

where widget can be any widget. The result would be this:

http://mess.hu/download/python/htmlhint.jpg

The HtmlHint component is connected to a "clipart provider" which serves the images (overriding some methods in wx.HtmlWindow). I'm very close to the final solution. I only have one big problem. The HTML format is resolution independent. I have no clue how to determine the optimal size of the hint window. But I have to do it somehow. Usually, the hint will contain text and possibly a few small icons only. Unfortunately, the HTML renderer will be different on different operating systems, and I cannot even calculate the size of the text.

It is not an easy question, and I do not expect to get a perfect solution here. I'm willing to work hard on this, but I would like to get some ideas. I believe this component will be good enough so I can make it freely available for everyone. I have a similar solution in Delphi and it looks very attractive:

http://mess.hu/images/cerebellum/elojegyzes_big.jpg

I bought the Delphi version of the HTML hint component. Somehow they solved the sizing problems, but they are using a fixed rendering engine and they only allow a small number of HTML tags.

  Les

Laszlo Zsolt Nagy wrote:

Hello Folks,

I'm working on a HTML based hint component. Works this way:

HtmlHint(widget,"<img src=\"16/query\"> This is a test hint")

where widget can be any widget. The result would be this:

http://mess.hu/download/python/htmlhint.jpg

The HtmlHint component is connected to a "clipart provider" which serves the images (overriding some methods in wx.HtmlWindow). I'm very close to the final solution. I only have one big problem. The HTML format is resolution independent. I have no clue how to determine the optimal size of the hint window. But I have to do it somehow. Usually, the hint will contain text and possibly a few small icons only. Unfortunately, the HTML renderer will be different on different operating systems, and I cannot even calculate the size of the text.

It is not an easy question, and I do not expect to get a perfect solution here. I'm willing to work hard on this, but I would like to get some ideas. I believe this component will be good enough so I can make it freely available for everyone. I have a similar solution in Delphi and it looks very attractive:

http://mess.hu/images/cerebellum/elojegyzes_big.jpg

I bought the Delphi version of the HTML hint component. Somehow they solved the sizing problems, but they are using a fixed rendering engine and they only allow a small number of HTML tags.

I have done something similar, I have html message boxes and tip windows. The solution I came up with isn't perfect, but I decided it was acceptable. Basically I decide on a width then resize the html window. I then set the height of the window to the virtual height of the htmlwindow, but I have to compensate a little for borders and scrollbars. I can post code some code if you would like, but it is a little ugly!

Regards,

Will McGugan

Will McGugan wrote:

Laszlo Zsolt Nagy wrote:

I'm working on a HTML based hint component. Works this way:

HtmlHint(widget,"<img src=\"16/query\"> This is a test hint")

...

I bought the Delphi version of the HTML hint component. Somehow they solved the sizing problems, but they are using a fixed rendering engine and they only allow a small number of HTML tags.

I have done something similar, I have html message boxes and tip windows. The solution I came up with isn't perfect, but I decided it was acceptable. Basically I decide on a width then resize the html window. I then set the height of the window to the virtual height of the htmlwindow, but I have to compensate a little for borders and scrollbars. I can post code some code if you would like, but it is a little ugly!

Oh yes, please! If you don't mind sharing your code. :slight_smile: I was thinking about the same, but I did not know that I'm able to get the 'virtual height' from the htmlwindow. It would be very nice. I'm sure it is not uglier than my code right now. :slight_smile:

  Les

Laszlo Zsolt Nagy wrote:

Oh yes, please! If you don't mind sharing your code. :slight_smile: I was thinking about the same, but I did not know that I'm able to get the 'virtual height' from the htmlwindow. It would be very nice. I'm sure it is not uglier than my code right now. :slight_smile:

Heres the function I use for my PopUp html window. Getting it just right so it doesnt scroll was tricky, and unfortunately it leaves a space at the bottom of the window. Doesnt look too bad though.

    def FitHtml(self):

        htmlwin = self.html_win
        width = self.width

        self.SetSize((width, self.GetSize().height))
        w, h = self.GetClientSize()
        self.html_win.SetSize(wx.Size(w,h))

        vx, vy = self.html_win.GetVirtualSize()

        scrx = wx.SystemSettings_GetMetric(wx.SYS_VSCROLL_X)
        scry = wx.SystemSettings_GetMetric(wx.SYS_HSCROLL_Y)

        self.html_win.SetWindowStyle(wx.html.HW_SCROLLBAR_NEVER)
        self.SetSize(wx.Size(vx+2+scrx, vy+2))

This is the code I used for my html message box. It is a little more complicated because the html is not the only control in the window..

        self.SetSize((width, self.GetSize().height))
        self.Layout()

        #html_size = htmlwin.GetVirtualSize()
        #size = htmlwin.GetSize()
        #height_mod = max(0, html_size.height - size.height)
        #self.SetSize(wx.Size(width, self.GetSize().height+height_mod))
        #self.Layout()

        html_size = htmlwin.GetVirtualSize()
        size = htmlwin.GetSize()
        height_mod = html_size.height - size.height
        scrx = wx.SystemSettings_GetMetric(wx.SYS_VSCROLL_X)
        scry = wx.SystemSettings_GetMetric(wx.SYS_HSCROLL_Y)
        html_size[0]+=scrx+scrx
        #html_size[1]+=scry
        htmlwin.SetSizeHints(html_size[0],html_size[1],html_size[0],html_size[1])
        self.Fit()
        #self.SetSize(wx.Size(width, self.GetSize().height+height_mod))

        dx, dy, dw, dh = wx.ClientDisplayRect()

        window_size = self.GetSize()

        #window_size.height = min(dh*.8, window_size.height)
        #self.SetSize(window_size)

        self.Layout()
        self.Refresh()

You can probably tell I've been tweaking it a lot. Let me know if you mange to improve upon it!

Will

This is the code I used for my html message box. It is a little more complicated because the html is not the only control in the window..

Yes, and there are more problems coming if you are using more sizers and more HTML windows in the same window.
I have a working solution for this, but it is very ugly too. :slight_smile:

First, I create a descendant with a 'GetMinSize' method:

class MegaHtmlWin(wx.html.HtmlWindow):
    def GetMinSize(self):
        """Calculate minimum client size needed hide scrollbars.

        Special thanks goes to Will McGuan <willmcgugan@gmail.com>."""
        w, h = self.GetClientSize()
        vx, vy = self.GetVirtualSize()
        scrx = wx.SystemSettings_GetMetric(wx.SYS_VSCROLL_X)
        scry = wx.SystemSettings_GetMetric(wx.SYS_HSCROLL_Y) return wx.Size(vx+2+scrx,vy+2)

Here is an example window that contains a MegaHtmlWin instance:

class HtmlHintWindow(wx.Frame):
    def __init__(self,pos):
        wx.Frame.__init__(
            self,id=-1,parent=None,title='',pos=pos,
            style = wx.STAY_ON_TOP | wx.SIMPLE_BORDER | wx.FRAME_NO_TASKBAR
        )
        s = self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.SetSizer(s)
        w = self.htmlwin = MegaHtmlWin(
            self,
            config = self.config
        ) w.SetText(hint)
        self.wsizer = wsizer = wx.BoxSizer(wx.HORIZONTAL)
        wsizer.Add(w,proportion=1,flag=wx.EXPAND)
        minwidth = 300 # I changed this for the example...
        wsizer.SetMinSize((minwidth,10))
        s.Add(wsizer,proportion=1,flag=wx.EXPAND) s.SetSizeHints(self)
    def Fit(self):
        new_minsize = self.htmlwin.GetMinSize()
        self.wsizer.SetMinSize(new_minsize)
        self.sizer.SetSizeHints(self)

This is how I display the frame:

            self.hintwindow.Show(True)
            self.hintwindow.Fit()

Of course this is ugly, because the sizer fits the frame twice. The advantage is that it works with more html windows and it is independent of the frame itself - the frame could contain any number of widgets added to self.sizer. You can even have more HTML windows, just you need to call SetMinSize/GetMinSize for each in the Fit() method. Still, you have to calculate the minimum width of the HTML window(s) but usually this is not a big problem. :slight_smile:

Thank a lot

  Les

This is the final result. :slight_smile:

http://mess.hu/download/python/htmlhint2.jpg