WindowFactory cannot be found for Custom Window-based Class

For help with general CEGUI usage:
- Questions about the usage of CEGUI and its features, if not explained in the documentation.
- Problems with the CMAKE configuration or problems occuring during the build process/compilation.
- Errors or unexpected behaviour.

Moderators: CEGUI MVP, CEGUI Team

mithryanna
Just popping in
Just popping in
Posts: 13
Joined: Fri Jun 25, 2010 15:00
Location: USA

WindowFactory cannot be found for Custom Window-based Class

Postby mithryanna » Wed Nov 24, 2010 19:28

A little bit of background on our application:

We are running CEGUI 7.2. (We don't have time to test and integrate our app with 7.5 before our deadline is up next month. 9_9)

We are using openscenegraph for our renderer. We have one 'main' layout that contains things like our sidebar panel with the main buttons and widgets; all spawned windows are in separate layout files. While testing out how to make custom widgets we turned 2 of these windows--our 'toolbox window' and our 'maplayers window' into widgets. We really only needed framewindow-derived classes to handle events and such, but it was a learning experience. So both of these classes have their own looknfeels defined that has all of their buttons and listboxes and such defined as children under the looknfeel instead of using the framewindow looknfeel and defining/positioning their children in the layout file. The layout files basically just define the size and starting position of our spawned windows.

We have another custom class representing a specific popup menu we wanted. I defined this in the scheme file same as our other windows, but unlike with the windows I didn't define a separate looknfeel for it and instead used the base popupmenu looknfeel like so:

Code: Select all

<FalagardMapping WindowType="Immersive_Border/ToolsPopupMenu" TargetType="CEGUI/PopupMenu" Renderer="Falagard/PopupMenu" LookNFeel="Immersive_Border/PopupMenu" />


The ToolsPopupMenu is programmatically created, so there is no layout file associated with it.

The current problem:

I am creating a new spawned window, but I want to do it differently than the first two: I want all of the different child buttons and other widgets to be placed in the layout file, not in the looknfeel, so it's easier for us to position and manipulate these later. I approached this task much like I did the ToolsPopupMenu: I am making a class to handle the events associated with this particular window, but don't want to define the layout in the looknfeel. I don't think our spawned windows should be custom widgets since they're not meant to be reused.

I made my class for the window--the LocatorWindow--and like our other spawned windows it derives from CEGUI::FrameWindow (actually, from our own FrameWindow which is really just (inherits from) a CEGUI::FrameWindow with the close button behavior defined so that we didn't have to do this for all of our framewindows).

.h file:

Code: Select all

namespace is_ui
{
    class LocatorWindow : public FrameWindow
    {
   public:
       LocatorWindow(const CEGUI::String &type, const CEGUI::String &name);
       ~LocatorWindow(void);
            static const CEGUI::String WidgetTypeName;

       CEGUI::Editbox* getLat();
       CEGUI::Editbox* getLong();
       CEGUI::Editbox* getAlt();
       virtual void initialiseComponents();
       bool OnEventSearch(const CEGUI::EventArgs& e);

   private:
       osgEarthUtil::EarthManipulator* _cameraManipulator;
       CEGUI::Editbox* _lat;
       CEGUI::Editbox* _long;
       CEGUI::Editbox* _alt;
       CEGUI::PushButton* _search;
    };
}


.cpp file:

Code: Select all

namespace is_ui
{
    const CEGUI::String LocatorWindow::WidgetTypeName("Immersive_Border/LocatorWindow");

    LocatorWindow::LocatorWindow(const CEGUI::String &type, const CEGUI::String &name) : FrameWindow(type, name)
    {
   _cameraManipulator = 0;
   _lat = 0;
   _long = 0;
   _alt = 0;
   _search = 0;
    }

    LocatorWindow::~LocatorWindow()
    {
    }

    CEGUI::Editbox* LocatorWindow::getLat()
    {
   return _lat;
    }

    CEGUI::Editbox* LocatorWindow::getLong()
    {
   return _long;
    }

    CEGUI::Editbox* LocatorWindow::getAlt()
    {
   return _alt;
    }

    void LocatorWindow::initialiseComponents()
    {
        FrameWindow::initialiseComponents();

   CEGUI::WindowManager& winMgr = CEGUI::WindowManager::getSingleton();

   _lat = static_cast<CEGUI::Editbox*>(winMgr.getWindow(this->getName() + "/lat"));
   _long = static_cast<CEGUI::Editbox*>(winMgr.getWindow(this->getName() + "/long"));
   _alt = static_cast<CEGUI::Editbox*>(winMgr.getWindow(this->getName() + "/alt"));
   _search = static_cast<CEGUI::PushButton*>(winMgr.getWindow(this->getName() + "/SearchButton"));

   _search->subscribeEvent(CEGUI::PushButton::EventClicked, CEGUI::Event::Subscriber(&LocatorWindow::OnEventSearch, this));
    }

    bool LocatorWindow::OnEventSearch(const CEGUI::EventArgs &e)
    {
   _cameraManipulator = is_graphics::GraphicsManager::getInstance()->getRenderer()->getEarthCameraManipulator();

   double usrLat = atof( _lat->getText().c_str() );
   double usrLong = atof( _long->getText().c_str() );
   double usrAlt = 4e6;

   if( usrLat < 180 && usrLat > -180 )
   {
       if( usrLong < 180 && usrLong > -180 )
       {
      _cameraManipulator->setViewpoint( osgEarthUtil::Viewpoint( osg::Vec3d( usrLat, usrLong, 0.0 ), 0.0, -90.0, usrAlt), 4.0 );
       }
   }

   return true;
    }

} // namespace is_ui


As you can see I named this window type Immersive_Border/LocatorWindow . I gave it a window factory as I did with all of our custom classes/widgets:

Code: Select all

void UiManager::bindCeguiWidgets()
{
    CEGUI::WindowFactoryManager& wfMgr = CEGUI::WindowFactoryManager::getSingleton();

    CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<FrameWindow> >();
    CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<LocatorWindow> >();
    CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<MapLayerItemEntry> >();
    CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<MapLayersWindow> >();
    CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<ToolboxWindow> >();
    CEGUI::WindowFactoryManager::addFactory<CEGUI::TplWindowFactory<ToolsPopupMenu> >();
}


Finally, I added it to the scheme file:

Code: Select all

   <FalagardMapping WindowType="Immersive_Border/LocatorWindow"  TargetType="CEGUI/FrameWindow" Renderer="Falagard/FrameWindow"  LookNFeel="Immersive_Border/FrameWindow" />


In the .layout file for the window, where it used to be an Immersive_Border/FrameWindow, I changed it to an Immersive_Border/LocatorWindow:

Code: Select all

<Window Type="Immersive_Border/LocatorWindow" Name="LocatorWindow" >


Essentially I've treated this window the same as our other windows, except that in the .layout file under our LocatorWindow it has children textboxes and such, and the LocatorWindow is supposed to follow the looknfeel of the Immersive_Border/FrameWindow instead of a custom Immersive_Border/LocatorWindow looknfeel. However, whereas the other windows spawn fine when I click the gui buttons to open them, attempting to spawn the LocatorWindow causes the application to freeze up and throw an exception in the console window.

CEGUI::UnknownObjectException in file c:\cegui-0.7.2-vc8\cegui\src\ceguiproperty
set.cpp(124) : There is no Property named 'Clickable' available in the set.
CEGUI::UnknownObjectException in file c:\cegui-0.7.2-vc8\cegui\src\ceguiwindowma
nager.cpp(256) : WindowManager::getWindow - A Window object with the name 'Locat
orWindow/lat' does not exist within the system
CEGUI::InvalidRequestException in file c:\cegui-0.7.2-vc8\cegui\src\ceguiguilayo
ut_xmlhandler.cpp(233) : GUILayout_xmlHandler::startElement - layout loading has
been aborted since no WindowFactory is available for 'Immersive_Border/LocatorW
indow' objects.


A similar error is recorded in the CEGUI log:

24/11/2010 11:51:00 (Error) CEGUI::UnknownObjectException in file c:\cegui-0.7.2-vc8\cegui\src\ceguiwindowmanager.cpp(256) : WindowManager::getWindow - A Window object with the name 'LocatorWindow/lat' does not exist within the system
24/11/2010 11:51:00 (Error) CEGUI::InvalidRequestException in file c:\cegui-0.7.2-vc8\cegui\src\ceguiguilayout_xmlhandler.cpp(233) : GUILayout_xmlHandler::startElement - layout loading has been aborted since no WindowFactory is available for 'Immersive_Border/LocatorWindow' objects.
24/11/2010 11:51:00 (Error) WindowManager::loadWindowLayout - loading of layout from file 'Immersive_LocatorWindow.layout' failed.



I should mention that before I converted the layout file to use Immersive_Border/LocatorWindow as a window type, the window would render just fine, but since it was an Immersive_Border/FrameWindow instead of our LocatorWindow class, it didn't respond to input as we had programmed into our class. As soon as I switched the window type in the layout it started telling me the above errors--that it doesn't have a windowfactory. I thought that by adding it to our scheme file and creating a windowfactory in our application we shouldn't have these issues. Really, I don't see why this doesn't work and yet our other windows do; the differences are mostly stylistic and dealing with children windows, but should have no bearing on this. But then I would also expect it to throw the error about not having a window factory BEFORE it says it can't find LocatorWindow/lat (one of the child windows--no duh it can't be found before the parent is created!)...

Can you shed any light on this? I want to be able to model all of our windows after this approach instead of the old one, but I can't do that until I figure out why it's not working with this first window!

Also, I can post the complete CEGUI log if need be but thought I would save you the trouble by just posting the relevant error and telling you what version we're running. If you need other info from it, though, let me know.

Jamarr
CEGUI MVP
CEGUI MVP
Posts: 812
Joined: Tue Jun 03, 2008 23:59
Location: USA

Re: WindowFactory cannot be found for Custom Window-based Class

Postby Jamarr » Mon Nov 29, 2010 23:11

Did you ever figure out your problem here? I am not well versed in this department, but I can tell that your approach sounds "odd". It sounds like you are trying to fix your "missing input" problem by re-defining the LocatorWindow as a widget, while leaving it implemented as a layout; this sounds crazy. Also, I assume the reason the exception messages appear "reversed" is because exceptions are thrown/caught in reverse order (as the stack unwinds).

Anyway, it is a bad idea to try and fix a problem by re-factoring / re-organizing the problem area without first understanding the actual cause. I would instead suggest focusing on why your window is not "responding to input". I imagine that this is a far easier problem to diagnose and resolve.
If somebody helps you by replying to your thread, upvote him/her as a thanks! Make sure to include your CEGUI.log and everything you tried when posting! And remember that we are not magicians!

mithryanna
Just popping in
Just popping in
Posts: 13
Joined: Fri Jun 25, 2010 15:00
Location: USA

Re: WindowFactory cannot be found for Custom Window-based Class

Postby mithryanna » Wed Dec 01, 2010 18:20

Never figured it out. But I do understand the reason it's not handling input. I guess I worded this poorly; I don't mean that it is not handling ANY input. I just mean the event handlers we wrote for our window aren't being called, and this is to be expected because if the layout file is loading a frame window and not a locator window, then it uses the frame window class and its event handlers.

The reason I made a locator window widget was in order to tell the layout that we want to use our locator window class.

I know what I'm doing sounds odd. Our team hasn't worked with CEGUI before and we're struggling to integrate it with openscenegraph; I'm the one who has been figuring out most of the CEGUI work and I'm only a junior developer. My thought/what I'm trying to do is this: as with any gui, we have specific windows we are going to use. These windows are made up of controls (aka widgets), many of which are interactive and will trigger event handlers. So much like what I've seen done in MFC and .NET (my only other non-web-based gui work), I made classes for each of my windows, with pointers to their controls and methods for their event handlers. The thing is, in order to determine the layout of these window widgets without programmatically setting their position, I need to either use a layout or a looknfeel. Using a looknfeel just seems odd to me because it's not like my LocatorWindow is a reusable widget, or even has a common skin with another widget. This is why I was trying to use a layout file.

I hope this better explains why I'm in this situation in the first place. I AM curious how most people create their gui windows, whether they create them 100% programmatically or use scripting for the events, make them custom widgets with a skin or layout, etc.


Return to “Help”

Who is online

Users browsing this forum: No registered users and 19 guests