SOLVED CUSTOMGUI_FONTCHOOSER Text Disappears

Hello,
I'm having an issue where, when I release my mouse click outside of my font chooser, the text disappears until a new font is chosen. The Command function is still receiving a FontData BaseContainer message even when nothing is showing in the FontChooser.

How can I prevent this disappearance from happening?

Font Chooser

import c4d, random
from c4d import gui

GADGET_ID_GEUSERAREA = 10000
FONT_CHOOSER = 10001
SLIDER_ID = 10002

class ExampleDialog(c4d.gui.GeDialog):
    fontChooser = None

    def CreateLayout(self):
        self.SetTitle("Font Chooser")
        self.GroupBorderSpace(50,50,50,50)
        self.fontChooser = self.AddCustomGui(FONT_CHOOSER, c4d.CUSTOMGUI_FONTCHOOSER, "Bitmap Button", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0)
        return True

    def InitValues(self):
        defaultFont = c4d.bitmaps.GeClipMap.GetDefaultFont(c4d.GE_FONT_DEFAULT_SYSTEM)
        defaultFontName = c4d.bitmaps.GeClipMap.GetFontName(defaultFont, c4d.GE_FONT_NAME_POSTSCRIPT)
        defaultFontBC = c4d.bitmaps.GeClipMap.GetFontDescription(defaultFontName, c4d.GE_FONT_NAME_POSTSCRIPT)
        self.fontChooser.SetFont(defaultFontBC)
        return True

    def Command(self,id,msg):
        print(id)
        for cid,val in msg:
            print(cid,val)
        return True

def main():
    global dlg
    dlg = ExampleDialog()
    dlg.Open(c4d.DLG_TYPE_ASYNC, pluginid=1234567, xpos=-2, ypos=-2, defaultw=600, defaulth=300)


if __name__ == "__main__":
    main()

Thank you!

Hi @blastframe,

thank you for reaching out to us. I can reproduce your problem and the font chooser dialog also behaves a bit dodgy regarding mouse clicks on some machines (mine for example). The dialog won't stay open unless you keep LMB pressed. So this also falls into the domain of something we will have to check.

Here I can however provide a little workaround for your problem. I personally would consider this to be a non-intended and rather brutish solution, but it will do what you want for now. But here applies the same as in your other thread, I will have to check if this is a bug or not.

Cheers,
Ferdinand

import c4d
import random
from c4d import gui

GADGET_ID_GEUSERAREA = 10000
FONT_CHOOSER = 10001
SLIDER_ID = 10002


class ExampleDialog(c4d.gui.GeDialog):
    """
    """
    fontChooser = None

    def __init__(self):
        """
        """
        self._currentFont = ExampleDialog._getDefaultFontDescription()

    @staticmethod
    def _getDefaultFontDescription():
        """Returns the description for the default font.
        """
        geClipMap = c4d.bitmaps.GeClipMap
        font = geClipMap.GetDefaultFont(c4d.GE_FONT_DEFAULT_SYSTEM)
        fontName = geClipMap.GetFontName(font, c4d.GE_FONT_NAME_POSTSCRIPT)
        return geClipMap.GetFontDescription(fontName, 
                                            c4d.GE_FONT_NAME_POSTSCRIPT)

    def _enforceFontSetting(self):
        """Enforces a the font data gadget to display a font setting.
        """
        gadget = self.FindCustomGui(FONT_CHOOSER, c4d.CUSTOMGUI_FONTCHOOSER)
        if not isinstance(gadget, c4d.gui.FontChooserCustomGui):
            raise RuntimeError("Could not access font gadget.")
        # GetFont() should not be able to return None, but you could also
        # take the safe route here and check first.
        self._currentFont = gadget.GetFont()
        # BaseCustomGui.Redraw() and .LayoutChanged() won't work. So we
        # take this rather brute force approach.
        gadget.SetFont(self._currentFont)

    def CreateLayout(self):
        """
        """
        self.SetTitle("Font Chooser")
        self.GroupBorderSpace(50, 50, 50, 50)
        self.fontChooser = self.AddCustomGui(
            FONT_CHOOSER, c4d.CUSTOMGUI_FONTCHOOSER, 
            "Bitmap Button", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0)
        return True

    def InitValues(self):
        self.fontChooser.SetFont(self._currentFont)
        return True

    def Command(self, mid, msg):
        """
        """
        if mid == FONT_CHOOSER:
            print ("Font Data Event")
            for cid, val in msg[c4d.BFM_ACTION_VALUE].GetFont():
                print (f"{cid}: {val}")
            # Enforce the font data display in the gadget.
            self._enforceFontSetting()
        return True


def main():
    """
    """
    global dlg
    dlg = ExampleDialog()
    dlg.Open(c4d.DLG_TYPE_ASYNC, pluginid=1234567,
             xpos=-2, ypos=-2, defaultw=600, defaulth=300)


if __name__ == "__main__":
    main()

Hi @blastframe,

thank you for reaching out to us. I can reproduce your problem and the font chooser dialog also behaves a bit dodgy regarding mouse clicks on some machines (mine for example). The dialog won't stay open unless you keep LMB pressed. So this also falls into the domain of something we will have to check.

Here I can however provide a little workaround for your problem. I personally would consider this to be a non-intended and rather brutish solution, but it will do what you want for now. But here applies the same as in your other thread, I will have to check if this is a bug or not.

Cheers,
Ferdinand

import c4d
import random
from c4d import gui

GADGET_ID_GEUSERAREA = 10000
FONT_CHOOSER = 10001
SLIDER_ID = 10002


class ExampleDialog(c4d.gui.GeDialog):
    """
    """
    fontChooser = None

    def __init__(self):
        """
        """
        self._currentFont = ExampleDialog._getDefaultFontDescription()

    @staticmethod
    def _getDefaultFontDescription():
        """Returns the description for the default font.
        """
        geClipMap = c4d.bitmaps.GeClipMap
        font = geClipMap.GetDefaultFont(c4d.GE_FONT_DEFAULT_SYSTEM)
        fontName = geClipMap.GetFontName(font, c4d.GE_FONT_NAME_POSTSCRIPT)
        return geClipMap.GetFontDescription(fontName, 
                                            c4d.GE_FONT_NAME_POSTSCRIPT)

    def _enforceFontSetting(self):
        """Enforces a the font data gadget to display a font setting.
        """
        gadget = self.FindCustomGui(FONT_CHOOSER, c4d.CUSTOMGUI_FONTCHOOSER)
        if not isinstance(gadget, c4d.gui.FontChooserCustomGui):
            raise RuntimeError("Could not access font gadget.")
        # GetFont() should not be able to return None, but you could also
        # take the safe route here and check first.
        self._currentFont = gadget.GetFont()
        # BaseCustomGui.Redraw() and .LayoutChanged() won't work. So we
        # take this rather brute force approach.
        gadget.SetFont(self._currentFont)

    def CreateLayout(self):
        """
        """
        self.SetTitle("Font Chooser")
        self.GroupBorderSpace(50, 50, 50, 50)
        self.fontChooser = self.AddCustomGui(
            FONT_CHOOSER, c4d.CUSTOMGUI_FONTCHOOSER, 
            "Bitmap Button", c4d.BFH_SCALEFIT | c4d.BFV_SCALEFIT, 0, 0)
        return True

    def InitValues(self):
        self.fontChooser.SetFont(self._currentFont)
        return True

    def Command(self, mid, msg):
        """
        """
        if mid == FONT_CHOOSER:
            print ("Font Data Event")
            for cid, val in msg[c4d.BFM_ACTION_VALUE].GetFont():
                print (f"{cid}: {val}")
            # Enforce the font data display in the gadget.
            self._enforceFontSetting()
        return True


def main():
    """
    """
    global dlg
    dlg = ExampleDialog()
    dlg.Open(c4d.DLG_TYPE_ASYNC, pluginid=1234567,
             xpos=-2, ypos=-2, defaultw=600, defaulth=300)


if __name__ == "__main__":
    main()

@ferdinand Thank you for the workaround. I'll wait to close this until you've found if it is a bug.

Hi @blastframe,

sure, I am working myself slowly but steadily through these issues of yours. This font thing here is the next on my plate 🙂

Cheers,
Ferdinand

Hi @blastframe,

so this is a bug that happens independently of Python. It also not connected to your example using a dangling dialog, but to the fact that it is using a dialog. When you implement some form of NodeData plugin and a FONT resource element in it, this bug won't happen.

I have opened a bug report for this. For now you would have to either use my little workaround or move outside of a GeDialog environment an implement the whole plugin as some form of NodeData plugin. If a dialog is of high priority for you, you could also display an instance of that node in a DescriptionCustomGui inside your dialog. Which should work and somewhat be a mix of both options.

Cheers,
Ferdinand