Guichan library and few examples, by Lubomyr

This commit is contained in:
Sergii Pylypenko
2013-11-26 20:46:06 +02:00
parent aa83519892
commit 0017de045f
133 changed files with 28296 additions and 0 deletions

View File

@@ -0,0 +1,233 @@
# The application settings for Android libSDL port
AppSettingVersion=19
# libSDL version to use (1.2 or 1.3, specify 1.3 for SDL2)
LibSdlVersion=1.2
# Specify application name (e.x. My Application)
AppName="GuiChan"
# Specify reversed site name of application (e.x. com.mysite.myapp)
AppFullName=com.guichan.sdl
# Specify screen orientation: (v)ertical/(p)ortrait or (h)orizontal/(l)andscape
ScreenOrientation=h
# Do not allow device to sleep when the application is in foreground, set this for video players or apps which use accelerometer
InhibitSuspend=n
# Specify path to download application data in zip archive in the form 'Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...'
# If you'll start Description with '!' symbol it will be enabled by default, other downloads should be selected by user from startup config menu
# If the URL in in the form ':dir/file.dat:http://URL/' it will be downloaded as binary BLOB to the application dir and not unzipped
# If the URL does not contain 'http://' it is treated as file from 'project/jni/application/src/AndroidData' dir -
# these files are put inside .apk package by build system
# Also please avoid 'https://' URLs, many Android devices do not have trust certificates and will fail to connect to SF.net over HTTPS
AppDataDownloadUrl="data file|files.zip"
# Video color depth - 16 BPP is the fastest and supported for all modes, 24 bpp is supported only
# with SwVideoMode=y, SDL_OPENGL mode supports everything. (16)/(24)/(32)
VideoDepthBpp=16
# Enable OpenGL depth buffer (needed only for 3-d applications, small speed decrease) (y) or (n)
NeedDepthBuffer=n
# Enable OpenGL stencil buffer (needed only for 3-d applications, small speed decrease) (y) or (n)
NeedStencilBuffer=n
# Try to use GLES 2.x context - will revert to GLES 1.X if unsupported by device
# you need this option only if you're developing 3-d app (y) or (n)
NeedGles2=n
# Application uses software video buffer - you're calling SDL_SetVideoMode() without SDL_HWSURFACE and without SDL_OPENGL,
# this will allow small speed optimization. Enable this even when you're using SDL_HWSURFACE. (y) or (n)
SwVideoMode=y
# Application video output will be resized to fit into native device screen (y)/(n)
SdlVideoResize=y
# Application resizing will keep 4:3 aspect ratio, with black bars at sides (y)/(n)
SdlVideoResizeKeepAspect=n
# Application does not call SDL_Flip() or SDL_UpdateRects() appropriately, or draws from non-main thread -
# enabling the compatibility mode will force screen update every 100 milliseconds, which is laggy and inefficient (y) or (n)
CompatibilityHacks=n
# Application initializes SDL audio/video inside static constructors (which is bad, you won't be able to run ndk-gdb) (y)/(n)
CompatibilityHacksStaticInit=n
# On-screen Android soft text input emulates hardware keyboard, this will only work with Hackers Keyboard app (y)/(n)
CompatibilityHacksTextInputEmulatesHwKeyboard=y
# Hack for broken devices: prevent audio chopping, by sleeping a bit after pushing each audio chunk (y)/(n)
CompatibilityHacksPreventAudioChopping=n
# Hack for broken apps: application ignores audio buffer size returned by SDL (y)/(n)
CompatibilityHacksAppIgnoresAudioBufferSize=n
# Hack for VCMI: preload additional shared libraries before aplication start
CompatibilityHacksAdditionalPreloadedSharedLibraries=""
# Hack for Free Heroes 2, which redraws the screen inside SDL_PumpEvents(): slow and compatible SDL event queue -
# do not use it with accelerometer/gyroscope, or your app may freeze at random (y)/(n)
CompatibilityHacksSlowCompatibleEventQueue=n
# Save and restore OpenGL state when drawing on-screen keyboard for apps that use SDL_OPENGL
CompatibilityHacksTouchscreenKeyboardSaveRestoreOpenGLState=
# Application uses SDL_UpdateRects() properly, and does not draw in any region outside those rects.
# This improves drawing speed, but I know only one application that does that, and it's written by me (y)/(n)
CompatibilityHacksProperUsageOfSDL_UpdateRects=
# Application uses mouse (y) or (n), this will show mouse emulation dialog to the user
AppUsesMouse=y
# Application needs two-button mouse, will also enable advanced point-and-click features (y) or (n)
AppNeedsTwoButtonMouse=y
# Show SDL mouse cursor, for applications that do not draw cursor at all (y) or (n)
ShowMouseCursor=n
# Generate more touch events, by default SDL generates one event per one video frame, this is useful for drawing apps (y) or (n)
GenerateSubframeTouchEvents=
# Force relative (laptop) mouse movement mode, useful when both on-screen keyboard and mouse are needed (y) or (n)
ForceRelativeMouseMode=n
# Application needs arrow keys (y) or (n), will show on-screen dpad/joystick (y) or (n)
AppNeedsArrowKeys=n
# Application needs text input (y) or (n), enables button for text input on screen
AppNeedsTextInput=y
# Application uses joystick (y) or (n), the on-screen DPAD will be used as joystick 0 axes 0-1
AppUsesJoystick=n
# Application uses second on-screen joystick, as SDL joystick 0 axes 2-3 (y)/(n)
AppUsesSecondJoystick=n
# Application uses accelerometer (y) or (n), the accelerometer will be used as joystick 1 axes 0-1 and 5-7
AppUsesAccelerometer=n
# Application uses gyroscope (y) or (n), the gyroscope will be used as joystick 1 axes 2-4
AppUsesGyroscope=n
# Application uses multitouch (y) or (n), multitouch events are passed as SDL_JOYBALLMOTION events for the joystick 0
AppUsesMultitouch=n
# Application records audio (it will use any available source, such a s microphone)
# API is defined in file SDL_android.h: int SDL_ANDROID_OpenAudioRecording(SDL_AudioSpec *spec); void SDL_ANDROID_CloseAudioRecording(void);
# This option will add additional permission to Android manifest (y)/(n)
AppRecordsAudio=n
# Application implements Android-specific routines to put to background, and will not draw anything to screen
# between SDL_ACTIVEEVENT lost / gained notifications - you should check for them
# rigth after SDL_Flip(), if (n) then SDL_Flip() will block till app in background (y) or (n)
# This option is reported to be buggy, sometimes failing to restore video state
NonBlockingSwapBuffers=y
# Redefine common hardware keys to SDL keysyms
# BACK hardware key is available on all devices, MENU is available on pre-ICS devices, other keys may be absent
# SEARCH and CALL by default return same keycode as DPAD_CENTER - one of those keys is available on most devices
# Use word NO_REMAP if you want to preserve native functionality for certain key (volume keys are 3-rd and 4-th)
# Keys: TOUCHSCREEN (works only when AppUsesMouse=n), DPAD_CENTER/SEARCH, VOLUMEUP, VOLUMEDOWN, MENU, BACK, CAMERA
RedefinedKeys="SPACE"
# Number of virtual keyboard keys (currently 6 is maximum)
AppTouchscreenKeyboardKeysAmount=0
# Number of virtual keyboard keys that support autofire (currently 2 is maximum)
AppTouchscreenKeyboardKeysAmountAutoFire=0
# Redefine on-screen keyboard keys to SDL keysyms - 6 keyboard keys + 4 multitouch gestures (zoom in/out and rotate left/right)
RedefinedKeysScreenKb="1 2 3 4 5 6 1 2 3 4"
# Names for on-screen keyboard keys, such as Fire, Jump, Run etc, separated by spaces, they are used in SDL config menu
RedefinedKeysScreenKbNames="1 2 3 4 5 6 1 2 3 4"
# On-screen keys theme
# 0 = Ultimate Droid by Sean Stieber (green, with gamepad joystick)
# 1 = Simple Theme by Beholder (white, with gamepad joystick)
# 2 = Sun by Sirea (yellow, with round joystick)
# 3 = Keen by Gerstrong (multicolor, with round joystick)
TouchscreenKeysTheme=2
# Redefine gamepad keys to SDL keysyms, button order is:
# A B X Y L1 R1 L2 R2 LThumb RThumb
RedefinedKeysGamepad="1 2 3 4 5 6 1 2 3 4"
# How long to show startup menu button, in msec, 0 to disable startup menu
StartupMenuButtonTimeout=3000
# Menu items to hide from startup menu, available menu items:
# SettingsMenu.OkButton SettingsMenu.DummyMenu SettingsMenu.MainMenu SettingsMenuMisc.DownloadConfig SettingsMenuMisc.OptionalDownloadConfig SettingsMenuMisc.AudioConfig SettingsMenuMisc.VideoSettingsConfig SettingsMenuMisc.ShowReadme SettingsMenuMisc.GyroscopeCalibration SettingsMenuMisc.ResetToDefaultsConfig SettingsMenuMouse.MouseConfigMainMenu SettingsMenuMouse.DisplaySizeConfig SettingsMenuMouse.LeftClickConfig SettingsMenuMouse.RightClickConfig SettingsMenuMouse.AdditionalMouseConfig SettingsMenuMouse.JoystickMouseConfig SettingsMenuMouse.TouchPressureMeasurementTool SettingsMenuMouse.CalibrateTouchscreenMenu SettingsMenuKeyboard.KeyboardConfigMainMenu SettingsMenuKeyboard.ScreenKeyboardSizeConfig SettingsMenuKeyboard.ScreenKeyboardDrawSizeConfig SettingsMenuKeyboard.ScreenKeyboardThemeConfig SettingsMenuKeyboard.ScreenKeyboardTransparencyConfig SettingsMenuKeyboard.RemapHwKeysConfig SettingsMenuKeyboard.RemapScreenKbConfig SettingsMenuKeyboard.ScreenGesturesConfig SettingsMenuKeyboard.CustomizeScreenKbLayout
HiddenMenuOptions=''
# Menu items to show at startup - this is Java code snippet, leave empty for default
# new SettingsMenuMisc.ShowReadme(), (AppUsesMouse \&\& \! ForceRelativeMouseMode \? new SettingsMenuMouse.DisplaySizeConfig(true) : new SettingsMenu.DummyMenu()), new SettingsMenuMisc.OptionalDownloadConfig(true), new SettingsMenuMisc.GyroscopeCalibration()
# Available menu items:
# SettingsMenu.OkButton SettingsMenu.DummyMenu SettingsMenu.MainMenu SettingsMenuMisc.DownloadConfig SettingsMenuMisc.OptionalDownloadConfig SettingsMenuMisc.AudioConfig SettingsMenuMisc.VideoSettingsConfig SettingsMenuMisc.ShowReadme SettingsMenuMisc.GyroscopeCalibration SettingsMenuMisc.ResetToDefaultsConfig SettingsMenuMouse.MouseConfigMainMenu SettingsMenuMouse.DisplaySizeConfig SettingsMenuMouse.LeftClickConfig SettingsMenuMouse.RightClickConfig SettingsMenuMouse.AdditionalMouseConfig SettingsMenuMouse.JoystickMouseConfig SettingsMenuMouse.TouchPressureMeasurementTool SettingsMenuMouse.CalibrateTouchscreenMenu SettingsMenuKeyboard.KeyboardConfigMainMenu SettingsMenuKeyboard.ScreenKeyboardSizeConfig SettingsMenuKeyboard.ScreenKeyboardDrawSizeConfig SettingsMenuKeyboard.ScreenKeyboardThemeConfig SettingsMenuKeyboard.ScreenKeyboardTransparencyConfig SettingsMenuKeyboard.RemapHwKeysConfig SettingsMenuKeyboard.RemapScreenKbConfig SettingsMenuKeyboard.ScreenGesturesConfig SettingsMenuKeyboard.CustomizeScreenKbLayout
FirstStartMenuOptions=''
# Enable multi-ABI binary, with hardware FPU support - it will also work on old devices,
# but .apk size is 2x bigger (y) / (n) / (x86) / (all)
MultiABI=all
# Minimum amount of RAM application requires, in Mb, SDL will print warning to user if it's lower
AppMinimumRAM=256
# Application version code (integer)
AppVersionCode=101
# Application user-visible version name (string)
AppVersionName="1.01"
# Reset SDL config when updating application to the new version (y) / (n)
ResetSdlConfigForThisVersion=n
# Delete application data files when upgrading (specify file/dir paths separated by spaces)
DeleteFilesOnUpgrade="%"
# Optional shared libraries to compile - removing some of them will save space
# MP3 support by libMAD is encumbered by patents and libMAD is GPL-ed
# Available libraries: mad (GPL-ed!) sdl_mixer sdl_image sdl_ttf sdl_net sdl_blitpool sdl_gfx sdl_sound intl xml2 lua jpeg png ogg flac tremor vorbis freetype xerces curl theora fluidsynth lzma lzo2 mikmod openal timidity zzip bzip2 yaml-cpp python boost_date_time boost_filesystem boost_iostreams boost_program_options boost_regex boost_signals boost_system boost_thread glu avcodec avdevice avfilter avformat avresample avutil swscale swresample bzip2
CompiledLibraries="sdl_image guichan"
# Application uses custom build script AndroidBuild.sh instead of Android.mk (y) or (n)
CustomBuildScript=n
# Aditional CFLAGS for application
AppCflags='-Wall -Wno-unused'
# Additional LDFLAGS for application
AppLdflags=''
# If application has headers with the same name as system headers, this option tries to fix compiler flags to make it compilable
AppOverlapsSystemHeaders=
# Build only following subdirs (empty will build all dirs, ignored with custom script)
AppSubdirsBuild=''
# Exclude these files from build
AppBuildExclude=''
# Application command line parameters, including app name as 0-th param
AppCmdline=''
# Here you may type readme text, which will be shown during startup. Format is:
# Text in English, use \\\\n to separate lines^de:Text in Deutsch^ru:Text in Russian, and so on (that's four backslashes, nice isn't it?)
ReadmeText='^Readme text'
# Screen size is used by Google Play to prevent an app to be installed on devices with smaller screens
# Minimum screen size that application supports: (s)mall / (m)edium / (l)arge
MinimumScreenSize=s
# Your AdMob Publisher ID, (n) if you don't want advertisements
AdmobPublisherId=n
# Your AdMob test device ID, to receive a test ad
AdmobTestDeviceId=
# Your AdMob banner size (BANNER/IAB_BANNER/IAB_LEADERBOARD/IAB_MRECT/IAB_WIDE_SKYSCRAPER/SMART_BANNER)
AdmobBannerSize=

View File

@@ -0,0 +1,23 @@
<container name="top" width="640" height="480">
<label name="logo_text" caption="Simple example of using XmlGui" />
<button x="5" y="20" name="exit" caption="Please click to exit" />
<icon name="logo" x="250" y="160" image="darkbitslogo_by_haiko.bmp" />
<dropdown name="dp" x="100" y="100">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</dropdown>
<listbox name="lb" x="200" y="100">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</listbox>
<textfield name="tf" text="simple text" x="5" y="300" />
<scrollarea name="sc" x="300" y="5" width="100" height="100">
<textbox name="tb" text="simple textbox
ddjdjd" />
</scrollarea>
<window name="wnd" caption="Drag me!" x="100" y="200">
<icon name="logo_in_wnd" x="0" y="0" image="darkbitslogo_by_haiko.bmp" />
</window>
</container>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,120 @@
/*
* Code that sets up an SDL application with Guichan using the
* Guichan SDL back end.
*/
#include <guichan.hpp>
#include <guichan/sdl.hpp>
namespace sdl
{
bool running = true;
SDL_Surface* screen;
// All back ends contain objects to make Guichan work on a
// specific target - in this case SDL - and they are a Graphics
// object to make Guichan able to draw itself using SDL, an
// input objec to make Guichan able to get user input using SDL
// and an ImageLoader object to make Guichan able to load images
// using SDL.
gcn::SDLGraphics* graphics;
gcn::SDLInput* input;
gcn::SDLImageLoader* imageLoader;
/**
* Initialises the SDL application. This function creates the global
* Gui object that can be populated by various examples.
*/
void init()
{
// We simply initialise SDL as we would do with any SDL application.
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE);
// We want unicode for the SDLInput object to function properly.
SDL_EnableUNICODE(1);
// We also want to enable key repeat.
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
// Now it's time to initialise the Guichan SDL back end.
imageLoader = new gcn::SDLImageLoader();
// The ImageLoader Guichan should use needs to be passed to the Image object
// using a static function.
gcn::Image::setImageLoader(imageLoader);
graphics = new gcn::SDLGraphics();
// The Graphics object needs a target to draw to, in this case it's the
// screen surface, but any surface will do, it doesn't have to be the screen.
graphics->setTarget(screen);
input = new gcn::SDLInput();
// Now we create the Gui object to be used with this SDL application.
globals::gui = new gcn::Gui();
// The Gui object needs a Graphics to be able to draw itself and an Input
// object to be able to check for user input. In this case we provide the
// Gui object with SDL implementations of these objects hence making Guichan
// able to utilise SDL.
globals::gui->setGraphics(graphics);
globals::gui->setInput(input);
}
/**
* Halts the SDL application.
*/
void halt()
{
delete globals::gui;
delete imageLoader;
delete input;
delete graphics;
SDL_Quit();
}
/**
* Runs the SDL application.
*/
void run()
{
// The main loop
while(running)
{
// Check user input
SDL_Event event;
while(SDL_PollEvent(&event))
{
if (event.type == SDL_KEYDOWN)
{
if (event.key.keysym.sym == SDLK_ESCAPE)
{
running = false;
}
if (event.key.keysym.sym == SDLK_f)
{
if (event.key.keysym.mod & KMOD_CTRL)
{
// Works with X11 only
SDL_WM_ToggleFullScreen(screen);
}
}
}
else if(event.type == SDL_QUIT)
{
running = false;
}
// After we have manually checked user input with SDL for
// any attempt by the user to halt the application we feed
// the input to Guichan by pushing the input to the Input
// object.
input->pushInput(event);
}
// Now we let the Gui object perform its logic.
globals::gui->logic();
// Now we let the Gui object draw itself.
globals::gui->draw();
// Finally we update the screen.
SDL_Flip(screen);
}
}
}

View File

@@ -0,0 +1,58 @@
/**
* This is an example that shows of the widgets present in
* Guichan. The example uses the SDL back end.
*/
#include <guichan.hpp>
#include <iostream>
// Here we store a global Gui object. We make it global
// so it's easily accessable. Of course, global variables
// should normally be avioded when it comes to OOP, but
// this examples is not an example that shows how to make a
// good and clean C++ application but merely an example
// that shows how to use Guichan.
namespace globals
{
gcn::Gui* gui;
}
// Include code to set up an SDL application with Guichan.
// The sdl.hpp file is responsible for creating and deleting
// the global Gui object.
#include "sdl.hpp"
// Include code to set up a Guichan GUI with all the widgets
// of Guichan. The code populates the global Gui object.
#include "widgets.hpp"
int main(int argc, char **argv)
{
try
{
sdl::init();
widgets::init();
sdl::run();
widgets::halt();
sdl::halt();
}
// Catch all Guichan exceptions.
catch (gcn::Exception e)
{
std::cerr << e.getMessage() << std::endl;
return 1;
}
// Catch all Std exceptions.
catch (std::exception e)
{
std::cerr << "Std exception: " << e.what() << std::endl;
return 1;
}
// Catch all unknown exceptions.
catch (...)
{
std::cerr << "Unknown exception" << std::endl;
return 1;
}
return 0;
}

View File

@@ -0,0 +1,182 @@
/**
* Code to populate a global Gui object with all the widgets
* of Guichan.
*/
namespace widgets
{
gcn::ImageFont* font;
gcn::Container* top;
gcn::Label* label;
gcn::Icon* icon;
gcn::Button* button;
gcn::TextField* textField;
gcn::TextBox* textBox;
gcn::ScrollArea* textBoxScrollArea;
gcn::ListBox* listBox;
gcn::DropDown* dropDown;
gcn::CheckBox* checkBox1;
gcn::CheckBox* checkBox2;
gcn::RadioButton* radioButton1;
gcn::RadioButton* radioButton2;
gcn::RadioButton* radioButton3;
gcn::Slider* slider;
gcn::Image *image;
gcn::Window *window;
gcn::Image *darkbitsImage;
gcn::Icon* darkbitsIcon;
gcn::TabbedArea* tabbedArea;
gcn::Button* tabOneButton;
gcn::CheckBox* tabTwoCheckBox;
/*
* List boxes and drop downs need an instance of a list model
* in order to display a list.
*/
class DemoListModel : public gcn::ListModel
{
public:
int getNumberOfElements()
{
return 5;
}
std::string getElementAt(int i)
{
switch(i)
{
case 0:
return std::string("zero");
case 1:
return std::string("one");
case 2:
return std::string("two");
case 3:
return std::string("three");
case 4:
return std::string("four");
default: // Just to keep warnings away
return std::string("");
}
}
};
DemoListModel demoListModel;
/**
* Initialises the widgets example by populating the global Gui
* object.
*/
void init()
{
// We first create a container to be used as the top widget.
// The top widget in Guichan can be any kind of widget, but
// in order to make the Gui contain more than one widget we
// make the top widget a container.
top = new gcn::Container();
// We set the dimension of the top container to match the screen.
top->setDimension(gcn::Rectangle(0, 0, 640, 480));
// Finally we pass the top widget to the Gui object.
globals::gui->setTop(top);
// Now we load the font used in this example.
font = new gcn::ImageFont("fixedfont.bmp", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
// Widgets may have a global font so we don't need to pass the
// font object to every created widget. The global font is static.
gcn::Widget::setGlobalFont(font);
// Now we create the widgets
label = new gcn::Label("Label");
image = gcn::Image::load("gui-chan.bmp");
icon = new gcn::Icon(image);
button = new gcn::Button("Button");
textField = new gcn::TextField("Text field");
textBox = new gcn::TextBox("Multiline\nText box");
textBoxScrollArea = new gcn::ScrollArea(textBox);
textBoxScrollArea->setWidth(200);
textBoxScrollArea->setHeight(100);
textBoxScrollArea->setFrameSize(1);
listBox = new gcn::ListBox(&demoListModel);
listBox->setFrameSize(1);
dropDown = new gcn::DropDown(&demoListModel);
checkBox1 = new gcn::CheckBox("Checkbox 1");
checkBox2 = new gcn::CheckBox("Checkbox 2");
radioButton1 = new gcn::RadioButton("RadioButton 1", "radiogroup", true);
radioButton2 = new gcn::RadioButton("RadioButton 2", "radiogroup");
radioButton3 = new gcn::RadioButton("RadioButton 3", "radiogroup");
slider = new gcn::Slider(0, 10);
slider->setSize(100, 10);
window = new gcn::Window("I am a window Drag me");
window->setBaseColor(gcn::Color(255, 150, 200, 190));
darkbitsImage = gcn::Image::load("darkbitslogo_by_haiko.bmp");
darkbitsIcon = new gcn::Icon(darkbitsImage);
window->add(darkbitsIcon);
window->resizeToContent();
tabbedArea = new gcn::TabbedArea();
tabbedArea->setSize(200, 100);
tabOneButton = new gcn::Button("A button in tab 1");
tabbedArea->addTab("Tab 1", tabOneButton);
tabTwoCheckBox = new gcn::CheckBox("A check box in tab 2");
tabbedArea->addTab("Tab 2", tabTwoCheckBox);
// Now it's time to add the widgets to the top container
// so they will be conected to the GUI.
top->add(label, 10, 10);
top->add(icon, 10, 30);
top->add(button, 200, 10);
top->add(textField, 250, 10);
top->add(textBoxScrollArea, 200, 50);
top->add(listBox, 200, 200);
top->add(dropDown, 500, 10);
top->add(checkBox1, 500, 130);
top->add(checkBox2, 500, 150);
top->add(radioButton1, 500, 200);
top->add(radioButton2, 500, 220);
top->add(radioButton3, 500, 240);
top->add(slider, 500, 300);
top->add(window, 50, 350);
top->add(tabbedArea, 400, 350);
}
/**
* Halts the widgets example.
*/
void halt()
{
delete font;
delete top;
delete label;
delete icon;
delete button;
delete textField;
delete textBox;
delete textBoxScrollArea;
delete listBox;
delete dropDown;
delete checkBox1;
delete checkBox2;
delete radioButton1;
delete radioButton2;
delete radioButton3;
delete slider;
delete window;
delete darkbitsIcon;
delete darkbitsImage;
delete tabbedArea;
delete tabOneButton;
delete tabTwoCheckBox;
}
}

View File

@@ -0,0 +1,226 @@
# The application settings for Android libSDL port
AppSettingVersion=19
# libSDL version to use (1.2 or 1.3, specify 1.3 for SDL2)
LibSdlVersion=1.2
# Specify application name (e.x. My Application)
AppName="XMLGuiChan"
# Specify reversed site name of application (e.x. com.mysite.myapp)
AppFullName=com.guichan.xml
# Specify screen orientation: (v)ertical/(p)ortrait or (h)orizontal/(l)andscape
ScreenOrientation=h
# Do not allow device to sleep when the application is in foreground, set this for video players or apps which use accelerometer
InhibitSuspend=n
# Specify path to download application data in zip archive in the form 'Description|URL|MirrorURL^Description2|URL2|MirrorURL2^...'
# If you'll start Description with '!' symbol it will be enabled by default, other downloads should be selected by user from startup config menu
# If the URL in in the form ':dir/file.dat:http://URL/' it will be downloaded as binary BLOB to the application dir and not unzipped
# If the URL does not contain 'http://' it is treated as file from 'project/jni/application/src/AndroidData' dir -
# these files are put inside .apk package by build system
# Also please avoid 'https://' URLs, many Android devices do not have trust certificates and will fail to connect to SF.net over HTTPS
AppDataDownloadUrl="data file|files.zip"
# Video color depth - 16 BPP is the fastest and supported for all modes, 24 bpp is supported only
# with SwVideoMode=y, SDL_OPENGL mode supports everything. (16)/(24)/(32)
VideoDepthBpp=16
# Enable OpenGL depth buffer (needed only for 3-d applications, small speed decrease) (y) or (n)
NeedDepthBuffer=n
# Enable OpenGL stencil buffer (needed only for 3-d applications, small speed decrease) (y) or (n)
NeedStencilBuffer=n
# Try to use GLES 2.x context - will revert to GLES 1.X if unsupported by device
# you need this option only if you're developing 3-d app (y) or (n)
NeedGles2=n
# Application uses software video buffer - you're calling SDL_SetVideoMode() without SDL_HWSURFACE and without SDL_OPENGL,
# this will allow small speed optimization. Enable this even when you're using SDL_HWSURFACE. (y) or (n)
SwVideoMode=y
# Application video output will be resized to fit into native device screen (y)/(n)
SdlVideoResize=y
# Application resizing will keep 4:3 aspect ratio, with black bars at sides (y)/(n)
SdlVideoResizeKeepAspect=n
# Application does not call SDL_Flip() or SDL_UpdateRects() appropriately, or draws from non-main thread -
# enabling the compatibility mode will force screen update every 100 milliseconds, which is laggy and inefficient (y) or (n)
CompatibilityHacks=n
# Application initializes SDL audio/video inside static constructors (which is bad, you won't be able to run ndk-gdb) (y)/(n)
CompatibilityHacksStaticInit=n
# On-screen Android soft text input emulates hardware keyboard, this will only work with Hackers Keyboard app (y)/(n)
CompatibilityHacksTextInputEmulatesHwKeyboard=y
# Hack for broken devices: prevent audio chopping, by sleeping a bit after pushing each audio chunk (y)/(n)
CompatibilityHacksPreventAudioChopping=n
# Hack for broken apps: application ignores audio buffer size returned by SDL (y)/(n)
CompatibilityHacksAppIgnoresAudioBufferSize=n
# Hack for VCMI: preload additional shared libraries before aplication start
CompatibilityHacksAdditionalPreloadedSharedLibraries=""
# Hack for Free Heroes 2, which redraws the screen inside SDL_PumpEvents(): slow and compatible SDL event queue -
# do not use it with accelerometer/gyroscope, or your app may freeze at random (y)/(n)
CompatibilityHacksSlowCompatibleEventQueue=n
# Save and restore OpenGL state when drawing on-screen keyboard for apps that use SDL_OPENGL
CompatibilityHacksTouchscreenKeyboardSaveRestoreOpenGLState=
# Application uses mouse (y) or (n), this will show mouse emulation dialog to the user
AppUsesMouse=y
# Application needs two-button mouse, will also enable advanced point-and-click features (y) or (n)
AppNeedsTwoButtonMouse=y
# Show SDL mouse cursor, for applications that do not draw cursor at all (y) or (n)
ShowMouseCursor=n
# Force relative (laptop) mouse movement mode, useful when both on-screen keyboard and mouse are needed (y) or (n)
ForceRelativeMouseMode=n
# Application needs arrow keys (y) or (n), will show on-screen dpad/joystick (y) or (n)
AppNeedsArrowKeys=n
# Application needs text input (y) or (n), enables button for text input on screen
AppNeedsTextInput=y
# Application uses joystick (y) or (n), the on-screen DPAD will be used as joystick 0 axes 0-1
AppUsesJoystick=n
# Application uses second on-screen joystick, as SDL joystick 0 axes 2-3 (y)/(n)
AppUsesSecondJoystick=n
# Application uses accelerometer (y) or (n), the accelerometer will be used as joystick 1 axes 0-1 and 5-7
AppUsesAccelerometer=n
# Application uses gyroscope (y) or (n), the gyroscope will be used as joystick 1 axes 2-4
AppUsesGyroscope=n
# Application uses multitouch (y) or (n), multitouch events are passed as SDL_JOYBALLMOTION events for the joystick 0
AppUsesMultitouch=n
# Application records audio (it will use any available source, such a s microphone)
# API is defined in file SDL_android.h: int SDL_ANDROID_OpenAudioRecording(SDL_AudioSpec *spec); void SDL_ANDROID_CloseAudioRecording(void);
# This option will add additional permission to Android manifest (y)/(n)
AppRecordsAudio=n
# Application implements Android-specific routines to put to background, and will not draw anything to screen
# between SDL_ACTIVEEVENT lost / gained notifications - you should check for them
# rigth after SDL_Flip(), if (n) then SDL_Flip() will block till app in background (y) or (n)
# This option is reported to be buggy, sometimes failing to restore video state
NonBlockingSwapBuffers=y
# Redefine common hardware keys to SDL keysyms
# BACK hardware key is available on all devices, MENU is available on pre-ICS devices, other keys may be absent
# SEARCH and CALL by default return same keycode as DPAD_CENTER - one of those keys is available on most devices
# Use word NO_REMAP if you want to preserve native functionality for certain key (volume keys are 3-rd and 4-th)
# Keys: TOUCHSCREEN (works only when AppUsesMouse=n), DPAD_CENTER/SEARCH, VOLUMEUP, VOLUMEDOWN, MENU, BACK, CAMERA
RedefinedKeys="SPACE"
# Number of virtual keyboard keys (currently 6 is maximum)
AppTouchscreenKeyboardKeysAmount=0
# Number of virtual keyboard keys that support autofire (currently 2 is maximum)
AppTouchscreenKeyboardKeysAmountAutoFire=0
# Redefine on-screen keyboard keys to SDL keysyms - 6 keyboard keys + 4 multitouch gestures (zoom in/out and rotate left/right)
RedefinedKeysScreenKb="1 2 3 4 5 6 1 2 3 4"
# Names for on-screen keyboard keys, such as Fire, Jump, Run etc, separated by spaces, they are used in SDL config menu
RedefinedKeysScreenKbNames="1 2 3 4 5 6 1 2 3 4"
# On-screen keys theme
# 0 = Ultimate Droid by Sean Stieber (green, with gamepad joystick)
# 1 = Simple Theme by Beholder (white, with gamepad joystick)
# 2 = Sun by Sirea (yellow, with round joystick)
# 3 = Keen by Gerstrong (multicolor, with round joystick)
TouchscreenKeysTheme=2
# Redefine gamepad keys to SDL keysyms, button order is:
# A B X Y L1 R1 L2 R2 LThumb RThumb
RedefinedKeysGamepad="1 2 3 4 5 6 1 2 3 4"
# How long to show startup menu button, in msec, 0 to disable startup menu
StartupMenuButtonTimeout=3000
# Menu items to hide from startup menu, available menu items:
# SettingsMenu.OkButton SettingsMenu.DummyMenu SettingsMenu.MainMenu SettingsMenuMisc.DownloadConfig SettingsMenuMisc.OptionalDownloadConfig SettingsMenuMisc.AudioConfig SettingsMenuMisc.VideoSettingsConfig SettingsMenuMisc.ShowReadme SettingsMenuMisc.GyroscopeCalibration SettingsMenuMisc.ResetToDefaultsConfig SettingsMenuMouse.MouseConfigMainMenu SettingsMenuMouse.DisplaySizeConfig SettingsMenuMouse.LeftClickConfig SettingsMenuMouse.RightClickConfig SettingsMenuMouse.AdditionalMouseConfig SettingsMenuMouse.JoystickMouseConfig SettingsMenuMouse.TouchPressureMeasurementTool SettingsMenuMouse.CalibrateTouchscreenMenu SettingsMenuKeyboard.KeyboardConfigMainMenu SettingsMenuKeyboard.ScreenKeyboardSizeConfig SettingsMenuKeyboard.ScreenKeyboardDrawSizeConfig SettingsMenuKeyboard.ScreenKeyboardThemeConfig SettingsMenuKeyboard.ScreenKeyboardTransparencyConfig SettingsMenuKeyboard.RemapHwKeysConfig SettingsMenuKeyboard.RemapScreenKbConfig SettingsMenuKeyboard.ScreenGesturesConfig SettingsMenuKeyboard.CustomizeScreenKbLayout
HiddenMenuOptions=''
# Menu items to show at startup - this is Java code snippet, leave empty for default
# new SettingsMenuMisc.ShowReadme(), (AppUsesMouse \&\& \! ForceRelativeMouseMode \? new SettingsMenuMouse.DisplaySizeConfig(true) : new SettingsMenu.DummyMenu()), new SettingsMenuMisc.OptionalDownloadConfig(true), new SettingsMenuMisc.GyroscopeCalibration()
# Available menu items:
# SettingsMenu.OkButton SettingsMenu.DummyMenu SettingsMenu.MainMenu SettingsMenuMisc.DownloadConfig SettingsMenuMisc.OptionalDownloadConfig SettingsMenuMisc.AudioConfig SettingsMenuMisc.VideoSettingsConfig SettingsMenuMisc.ShowReadme SettingsMenuMisc.GyroscopeCalibration SettingsMenuMisc.ResetToDefaultsConfig SettingsMenuMouse.MouseConfigMainMenu SettingsMenuMouse.DisplaySizeConfig SettingsMenuMouse.LeftClickConfig SettingsMenuMouse.RightClickConfig SettingsMenuMouse.AdditionalMouseConfig SettingsMenuMouse.JoystickMouseConfig SettingsMenuMouse.TouchPressureMeasurementTool SettingsMenuMouse.CalibrateTouchscreenMenu SettingsMenuKeyboard.KeyboardConfigMainMenu SettingsMenuKeyboard.ScreenKeyboardSizeConfig SettingsMenuKeyboard.ScreenKeyboardDrawSizeConfig SettingsMenuKeyboard.ScreenKeyboardThemeConfig SettingsMenuKeyboard.ScreenKeyboardTransparencyConfig SettingsMenuKeyboard.RemapHwKeysConfig SettingsMenuKeyboard.RemapScreenKbConfig SettingsMenuKeyboard.ScreenGesturesConfig SettingsMenuKeyboard.CustomizeScreenKbLayout
FirstStartMenuOptions=''
# Enable multi-ABI binary, with hardware FPU support - it will also work on old devices,
# but .apk size is 2x bigger (y) / (n) / (x86) / (all)
MultiABI=n
# Minimum amount of RAM application requires, in Mb, SDL will print warning to user if it's lower
AppMinimumRAM=256
# Application version code (integer)
AppVersionCode=101
# Application user-visible version name (string)
AppVersionName="1.01"
# Reset SDL config when updating application to the new version (y) / (n)
ResetSdlConfigForThisVersion=n
# Delete application data files when upgrading (specify file/dir paths separated by spaces)
DeleteFilesOnUpgrade=""
# Optional shared libraries to compile - removing some of them will save space
# MP3 support by libMAD is encumbered by patents and libMAD is GPL-ed
# Available libraries: mad (GPL-ed!) sdl_mixer sdl_image sdl_ttf sdl_net sdl_blitpool sdl_gfx sdl_sound intl xml2 lua jpeg png ogg flac tremor vorbis freetype xerces curl theora fluidsynth lzma lzo2 mikmod openal timidity zzip bzip2 yaml-cpp python boost_date_time boost_filesystem boost_iostreams boost_program_options boost_regex boost_signals boost_system boost_thread glu avcodec avdevice avfilter avformat avresample avutil swscale swresample bzip2
CompiledLibraries="sdl_image guichan"
# Application uses custom build script AndroidBuild.sh instead of Android.mk (y) or (n)
CustomBuildScript=n
# Aditional CFLAGS for application
AppCflags='-Wall -Wno-unused -DGUICHAN_BUILD -fexceptions'
# Additional LDFLAGS for application
AppLdflags=''
# If application has headers with the same name as system headers, this option tries to fix compiler flags to make it compilable
AppOverlapsSystemHeaders=
# Build only following subdirs (empty will build all dirs, ignored with custom script)
AppSubdirsBuild=''
# Exclude these files from build
AppBuildExclude=''
# Application command line parameters, including app name as 0-th param
AppCmdline=''
# Here you may type readme text, which will be shown during startup. Format is:
# Text in English, use \\\\n to separate lines^de:Text in Deutsch^ru:Text in Russian, and so on (that's four backslashes, nice isn't it?)
ReadmeText='^Readme text'
# Screen size is used by Google Play to prevent an app to be installed on devices with smaller screens
# Minimum screen size that application supports: (s)mall / (m)edium / (l)arge
MinimumScreenSize=s
# Your AdMob Publisher ID, (n) if you don't want advertisements
AdmobPublisherId=n
# Your AdMob test device ID, to receive a test ad
AdmobTestDeviceId=
# Your AdMob banner size (BANNER/IAB_BANNER/IAB_LEADERBOARD/IAB_MRECT/IAB_WIDE_SKYSCRAPER/SMART_BANNER)
AdmobBannerSize=

View File

@@ -0,0 +1,23 @@
<container name="top" width="640" height="480">
<label name="logo_text" caption="Simple example of using XmlGui" />
<button x="5" y="20" name="exit" caption="Please click to exit" />
<icon name="logo" x="250" y="160" image="darkbitslogo_by_haiko.bmp" />
<dropdown name="dp" x="100" y="100">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</dropdown>
<listbox name="lb" x="200" y="100">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</listbox>
<textfield name="tf" text="simple text" x="5" y="300" />
<scrollarea name="sc" x="300" y="5" width="100" height="100">
<textbox name="tb" text="simple textbox
ddjdjd" />
</scrollarea>
<window name="wnd" caption="Drag me!" x="100" y="200">
<icon name="logo_in_wnd" x="0" y="0" image="darkbitslogo_by_haiko.bmp" />
</window>
</container>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@@ -0,0 +1,208 @@
/**
* SDL Hello World example for Guichan.
*/
// Include all necessary headers.
#include <iostream>
#include <guichan.hpp>
#include <guichan/sdl.hpp>
#include <SDL/SDL.h>
#include "xmlgui.h"
/*
* Common stuff we need
*/
bool running = true;
/*
* SDL Stuff we need
*/
SDL_Surface* screen;
SDL_Event event;
/*
* Guichan SDL stuff we need
*/
gcn::SDLInput* input; // Input driver
gcn::SDLGraphics* graphics; // Graphics driver
gcn::SDLImageLoader* imageLoader; // For loading images
/*
* Guichan stuff we need
*/
gcn::Gui* gui; // A Gui object - binds it all together
gcn::Container* top; // A top container
gcn::ImageFont* font; // A font
//XmlGui stuff
XmlGui *xmlgui = new XmlGui();
/**
* Initializes the Hello World
*/
void init()
{
/*
* Here we initialize SDL as we would do with any SDL application.
*/
SDL_Init(SDL_INIT_VIDEO);
screen = SDL_SetVideoMode(640, 480, 32, SDL_HWSURFACE);
// We want unicode
SDL_EnableUNICODE(1);
// We want to enable key repeat
SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
/*
* Now it's time for Guichan SDL stuff
*/
imageLoader = new gcn::SDLImageLoader();
// The ImageLoader in use is static and must be set to be
// able to load images
gcn::Image::setImageLoader(imageLoader);
graphics = new gcn::SDLGraphics();
// Set the target for the graphics object to be the screen.
// In other words, we will draw to the screen.
// Note, any surface will do, it doesn't have to be the screen.
graphics->setTarget(screen);
input = new gcn::SDLInput();
/*
* Last but not least it's time to initialize and create the gui
* with Guichan stuff.
*/
gui = new gcn::Gui();
// Set gui to use the SDLGraphics object.
gui->setGraphics(graphics);
// Set gui to use the SDLInput object
gui->setInput(input);
// Set the top container
gui->setTop(top);
// Load the image font.
font = new gcn::ImageFont("fixedfont.bmp", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
// The global font is static and must be set.
gcn::Widget::setGlobalFont(font);
xmlgui = new XmlGui();
xmlgui->parse("gui.xml");
gui->setTop(xmlgui->getWidget("top"));
}
/**
* Halts the application
*/
void halt()
{
/*
* Destroy Guichan stuff
*/
delete xmlgui;
delete font;
delete top;
delete gui;
/*
* Destroy Guichan SDL stuff
*/
delete input;
delete graphics;
delete imageLoader;
/*
* Destroy SDL stuff
*/
SDL_Quit();
}
/**
* Checks input. On escape halt the application.
*/
void checkInput()
{
/*
* Poll SDL events
*/
while(SDL_PollEvent(&event))
{
if (event.type == SDL_KEYDOWN)
{
if (event.key.keysym.sym == SDLK_ESCAPE)
{
running = false;
}
if (event.key.keysym.sym == SDLK_f)
{
if (event.key.keysym.mod & KMOD_CTRL)
{
// Works with X11 only
SDL_WM_ToggleFullScreen(screen);
}
}
}
else if(event.type == SDL_QUIT)
{
running = false;
}
/*
* Now that we are done polling and using SDL events we pass
* the leftovers to the SDLInput object to later be handled by
* the Gui. (This example doesn't require us to do this 'cause a
* label doesn't use input. But will do it anyway to show how to
* set up an SDL application with Guichan.)
*/
input->pushInput(event);
}
}
/**
* Runs the application
*/
void run()
{
while(running)
{
// Poll input
checkInput();
// Let the gui perform it's logic (like handle input)
gui->logic();
// Draw the gui
gui->draw();
// Update the screen
SDL_Flip(screen);
}
}
int main(int argc, char **argv)
{
try
{
init();
run();
halt();
}
/*
* Catch all Guichan exceptions
*/
catch (gcn::Exception e)
{
std::cerr << e.getMessage() << std::endl;
return 1;
}
/*
* Catch all Std exceptions
*/
catch (std::exception e)
{
std::cerr << "Std exception: " << e.what() << std::endl;
return 1;
}
/*
* Catch all Unknown exceptions
*/
catch (...)
{
std::cerr << "Unknown exception" << std::endl;
return 1;
}
return 0;
}

View File

@@ -0,0 +1,796 @@
/*
Copyright (c) 2000 Lee Thomason (www.grinninglizard.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "tinyxml.h"
#include <stdio.h>
#include <stdlib.h>
TiXmlNode::TiXmlNode( NodeType _type )
{
parent = 0;
type = _type;
firstChild = 0;
lastChild = 0;
prev = 0;
next = 0;
}
TiXmlNode::~TiXmlNode()
{
TiXmlNode* node = firstChild;
TiXmlNode* temp = 0;
while ( node )
{
temp = node;
node = node->next;
delete temp;
}
}
void TiXmlNode::Clear()
{
TiXmlNode* node = firstChild;
TiXmlNode* temp = 0;
while ( node )
{
temp = node;
node = node->next;
delete temp;
}
firstChild = 0;
lastChild = 0;
}
TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node )
{
node->parent = this;
node->prev = lastChild;
node->next = 0;
if ( lastChild )
lastChild->next = node;
else
firstChild = node; // it was an empty list.
lastChild = node;
return node;
}
TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis )
{
TiXmlNode* node = addThis.Clone();
if ( !node )
return 0;
return LinkEndChild( node );
}
TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis )
{
if ( beforeThis->parent != this )
return 0;
TiXmlNode* node = addThis.Clone();
if ( !node )
return 0;
node->parent = this;
node->next = beforeThis;
node->prev = beforeThis->prev;
beforeThis->prev->next = node;
beforeThis->prev = node;
return node;
}
TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis )
{
if ( afterThis->parent != this )
return 0;
TiXmlNode* node = addThis.Clone();
if ( !node )
return 0;
node->parent = this;
node->prev = afterThis;
node->next = afterThis->next;
afterThis->next->prev = node;
afterThis->next = node;
return node;
}
TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis )
{
if ( replaceThis->parent != this )
return 0;
TiXmlNode* node = withThis.Clone();
if ( !node )
return 0;
node->next = replaceThis->next;
node->prev = replaceThis->prev;
if ( replaceThis->next )
replaceThis->next->prev = node;
else
lastChild = node;
if ( replaceThis->prev )
replaceThis->prev->next = node;
else
firstChild = node;
delete replaceThis;
return node;
}
bool TiXmlNode::RemoveChild( TiXmlNode* removeThis )
{
if ( removeThis->parent != this )
{
assert( 0 );
return false;
}
if ( removeThis->next )
removeThis->next->prev = removeThis->prev;
else
lastChild = removeThis->prev;
if ( removeThis->prev )
removeThis->prev->next = removeThis->next;
else
firstChild = removeThis->next;
delete removeThis;
return true;
}
TiXmlNode* TiXmlNode::FirstChild( const std::string& value ) const
{
TiXmlNode* node;
for ( node = firstChild; node; node = node->next )
{
if ( node->Value() == value )
return node;
}
return 0;
}
TiXmlNode* TiXmlNode::LastChild( const std::string& value ) const
{
TiXmlNode* node;
for ( node = lastChild; node; node = node->prev )
{
if ( node->Value() == value )
return node;
}
return 0;
}
TiXmlNode* TiXmlNode::IterateChildren( TiXmlNode* previous )
{
if ( !previous )
{
return FirstChild();
}
else
{
//commented due Issue 1 (thanks copesetic)
//assert( previous->parent == this );
return previous->NextSibling();
}
}
TiXmlNode* TiXmlNode::IterateChildren( const std::string& val, TiXmlNode* previous )
{
if ( !previous )
{
return FirstChild( val );
}
else
{
assert( previous->parent == this );
return previous->NextSibling( val );
}
}
TiXmlNode* TiXmlNode::NextSibling( const std::string& value ) const
{
TiXmlNode* node;
for ( node = next; node; node = node->next )
{
if ( node->Value() == value )
return node;
}
return 0;
}
TiXmlNode* TiXmlNode::PreviousSibling( const std::string& value ) const
{
TiXmlNode* node;
for ( node = prev; node; node = node->prev )
{
if ( node->Value() == value )
return node;
}
return 0;
}
void TiXmlElement::RemoveAttribute( const std::string& name )
{
TiXmlAttribute* node = attributeSet.Find( name );
if ( node )
{
attributeSet.Remove( node );
delete node;
}
}
TiXmlElement* TiXmlNode::FirstChildElement() const
{
TiXmlNode* node;
for ( node = FirstChild();
node;
node = node->NextSibling() )
{
if ( node->ToElement() )
return node->ToElement();
}
return 0;
}
TiXmlElement* TiXmlNode::FirstChildElement( const std::string& value ) const
{
TiXmlNode* node;
for ( node = FirstChild( value );
node;
node = node->NextSibling( value ) )
{
if ( node->ToElement() )
return node->ToElement();
}
return 0;
}
TiXmlElement* TiXmlNode::NextSiblingElement() const
{
TiXmlNode* node;
for ( node = NextSibling();
node;
node = node->NextSibling() )
{
if ( node->ToElement() )
return node->ToElement();
}
return 0;
}
TiXmlElement* TiXmlNode::NextSiblingElement( const std::string& value ) const
{
TiXmlNode* node;
for ( node = NextSibling( value );
node;
node = node->NextSibling( value ) )
{
if ( node->ToElement() )
return node->ToElement();
}
return 0;
}
TiXmlDocument* TiXmlNode::GetDocument() const
{
const TiXmlNode* node;
for( node = this; node; node = node->parent )
{
if ( node->ToDocument() )
return node->ToDocument();
}
return 0;
}
// TiXmlElement::TiXmlElement()
// : TiXmlNode( TiXmlNode::ELEMENT )
// {
// }
TiXmlElement::TiXmlElement( const std::string& _value )
: TiXmlNode( TiXmlNode::ELEMENT )
{
firstChild = lastChild = 0;
value = _value;
}
TiXmlElement::~TiXmlElement()
{
while( attributeSet.First() )
{
TiXmlAttribute* node = attributeSet.First();
attributeSet.Remove( node );
delete node;
}
}
const std::string* TiXmlElement::Attribute( const std::string& name ) const
{
TiXmlAttribute* node = attributeSet.Find( name );
if ( node )
return &(node->Value() );
return 0;
}
const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const
{
const std::string* s = Attribute( name );
if ( s )
*i = atoi( s->c_str() );
else
*i = 0;
return s;
}
void TiXmlElement::SetAttribute( const std::string& name, int val )
{
char buf[64];
sprintf( buf, "%d", val );
std::string v = buf;
SetAttribute( name, v );
}
void TiXmlElement::SetAttribute( const std::string& name, const std::string& value )
{
TiXmlAttribute* node = attributeSet.Find( name );
if ( node )
{
node->SetValue( value );
return;
}
TiXmlAttribute* attrib = new TiXmlAttribute( name, value );
if ( attrib )
{
attributeSet.Add( attrib );
}
else
{
TiXmlDocument* document = GetDocument();
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
}
}
void TiXmlElement::Print( FILE* fp, int depth )
{
int i;
for ( i=0; i<depth; i++ )
fprintf( fp, " " );
fprintf( fp, "<%s", value.c_str() );
TiXmlAttribute* attrib;
for ( attrib = attributeSet.First(); attrib; attrib = attrib->Next() )
{
fprintf( fp, " " );
attrib->Print( fp, 0 );
}
// If this node has children, give it a closing tag. Else
// make it an empty tag.
TiXmlNode* node;
if ( firstChild )
{
fprintf( fp, ">" );
for ( node = firstChild; node; node=node->NextSibling() )
{
if ( !node->ToText() )
fprintf( fp, "\n" );
node->Print( fp, depth+1 );
}
fprintf( fp, "\n" );
for ( i=0; i<depth; i++ )
fprintf( fp, " " );
fprintf( fp, "</%s>", value.c_str() );
}
else
{
fprintf( fp, " />" );
}
}
TiXmlNode* TiXmlElement::Clone() const
{
TiXmlElement* clone = new TiXmlElement( Value() );
if ( !clone )
return 0;
CopyToClone( clone );
// Clone the attributes, then clone the children.
TiXmlAttribute* attribute = 0;
for( attribute = attributeSet.First();
attribute;
attribute = attribute->Next() )
{
clone->SetAttribute( attribute->Name(), attribute->Value() );
}
TiXmlNode* node = 0;
for ( node = firstChild; node; node = node->NextSibling() )
{
clone->LinkEndChild( node->Clone() );
}
return clone;
}
TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT )
{
error = false;
// factory = new TiXmlFactory();
}
TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT )
{
// factory = new TiXmlFactory();
value = documentName;
error = false;
}
// void TiXmlDocument::SetFactory( TiXmlFactory* f )
// {
// delete factory;
// factory = f;
// }
bool TiXmlDocument::LoadFile()
{
return LoadFile( value );
}
bool TiXmlDocument::SaveFile()
{
return SaveFile( value );
}
bool TiXmlDocument::LoadFile( const std::string& filename )
{
// Delete the existing data:
Clear();
// Load the new data:
FILE* fp = fopen( filename.c_str(), "r" );
if ( fp )
{
unsigned size;
fseek( fp, 0, SEEK_END );
size = ftell( fp );
fseek( fp, 0, SEEK_SET );
char* buf = new char[size+1];
char* p = buf;
while( fgets( p, size, fp ) )
{
p = strchr( p, 0 );
}
fclose( fp );
Parse( buf );
delete [] buf;
if ( !Error() )
return true;
}
else
{
SetError( TIXML_ERROR_OPENING_FILE );
}
return false;
}
bool TiXmlDocument::SaveFile( const std::string& filename )
{
FILE* fp = fopen( filename.c_str(), "w" );
if ( fp )
{
Print( fp, 0 );
fclose( fp );
return true;
}
return false;
}
TiXmlNode* TiXmlDocument::Clone() const
{
TiXmlDocument* clone = new TiXmlDocument();
if ( !clone )
return 0;
CopyToClone( clone );
clone->error = error;
clone->errorDesc = errorDesc;
TiXmlNode* node = 0;
for ( node = firstChild; node; node = node->NextSibling() )
{
clone->LinkEndChild( node->Clone() );
}
return clone;
}
void TiXmlDocument::Print( FILE* fp, int )
{
TiXmlNode* node;
for ( node=FirstChild(); node; node=node->NextSibling() )
{
node->Print( fp, 0 );
fprintf( fp, "\n" );
}
}
TiXmlAttribute* TiXmlAttribute::Next()
{
// We are using knowledge of the sentinel. The sentinel
// have a value or name.
if ( next->value.empty() && next->name.empty() )
return 0;
return next;
}
TiXmlAttribute* TiXmlAttribute::Previous()
{
// We are using knowledge of the sentinel. The sentinel
// have a value or name.
if ( prev->value.empty() && prev->name.empty() )
return 0;
return prev;
}
void TiXmlAttribute::Print( FILE* fp, int )
{
if ( value.find( '\"' ) != std::string::npos )
fprintf( fp, "%s='%s'", name.c_str(), value.c_str() );
else
fprintf( fp, "%s=\"%s\"", name.c_str(), value.c_str() );
}
void TiXmlComment::Print( FILE* fp, int depth )
{
for ( int i=0; i<depth; i++ )
fprintf( fp, " " );
fprintf( fp, "<!--%s-->", value.c_str() );
}
TiXmlNode* TiXmlComment::Clone() const
{
TiXmlComment* clone = new TiXmlComment();
if ( !clone )
return 0;
CopyToClone( clone );
return clone;
}
void TiXmlText::Print( FILE* fp, int )
{
fprintf( fp, "%s", value.c_str() );
}
TiXmlNode* TiXmlText::Clone() const
{
TiXmlText* clone = 0;
clone = new TiXmlText();
if ( !clone )
return 0;
CopyToClone( clone );
return clone;
}
TiXmlDeclaration::TiXmlDeclaration( const std::string& _version,
const std::string& _encoding,
const std::string& _standalone )
: TiXmlNode( TiXmlNode::DECLARATION )
{
version = _version;
encoding = _encoding;
standalone = _standalone;
}
void TiXmlDeclaration::Print( FILE* fp, int )
{
std::string out = "<?xml ";
if ( !version.empty() )
{
out += "version=\"";
out += version;
out += "\" ";
}
if ( !encoding.empty() )
{
out += "encoding=\"";
out += encoding;
out += "\" ";
}
if ( !standalone.empty() )
{
out += "standalone=\"";
out += standalone;
out += "\" ";
}
out += "?>";
fprintf( fp, "%s", out.c_str() );
}
TiXmlNode* TiXmlDeclaration::Clone() const
{
TiXmlDeclaration* clone = new TiXmlDeclaration();
if ( !clone )
return 0;
CopyToClone( clone );
clone->version = version;
clone->encoding = encoding;
clone->standalone = standalone;
return clone;
}
void TiXmlUnknown::Print( FILE* fp, int depth )
{
for ( int i=0; i<depth; i++ )
fprintf( fp, " " );
fprintf( fp, "<%s>", value.c_str() );
}
TiXmlNode* TiXmlUnknown::Clone() const
{
TiXmlUnknown* clone = new TiXmlUnknown();
if ( !clone )
return 0;
CopyToClone( clone );
return clone;
}
TiXmlAttributeSet::TiXmlAttributeSet()
{
sentinel.next = &sentinel;
sentinel.prev = &sentinel;
}
TiXmlAttributeSet::~TiXmlAttributeSet()
{
assert( sentinel.next == &sentinel );
assert( sentinel.prev == &sentinel );
}
void TiXmlAttributeSet::Add( TiXmlAttribute* addMe )
{
assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set.
addMe->next = &sentinel;
addMe->prev = sentinel.prev;
sentinel.prev->next = addMe;
sentinel.prev = addMe;
}
void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe )
{
TiXmlAttribute* node;
for( node = sentinel.next; node != &sentinel; node = node->next )
{
if ( node == removeMe )
{
node->prev->next = node->next;
node->next->prev = node->prev;
node->next = 0;
node->prev = 0;
return;
}
}
assert( 0 ); // we tried to remove a non-linked attribute.
}
TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const
{
TiXmlAttribute* node;
for( node = sentinel.next; node != &sentinel; node = node->next )
{
if ( node->Name() == name )
return node;
}
return 0;
}

View File

@@ -0,0 +1,613 @@
/*
Copyright (c) 2000 Lee Thomason (www.grinninglizard.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#ifndef TINYXML_INCLUDED
#define TINYXML_INCLUDED
#pragma warning( disable : 4530 )
#pragma warning( disable : 4786 )
#include <string>
#include <stdio.h>
#include <assert.h>
class TiXmlDocument;
class TiXmlElement;
class TiXmlComment;
class TiXmlUnknown;
class TiXmlAttribute;
class TiXmlText;
class TiXmlDeclaration;
/** TiXmlBase is a base class for every class in TinyXml.
It does little except to establist that TinyXml classes
can be printed and provide some utility functions.
In XML, the document and elements can contain
other elements and other types of nodes.
@verbatim
A Document can contain: Element (container or leaf)
Comment (leaf)
Unknown (leaf)
Declaration( leaf )
An Element can contain: Element (container or leaf)
Text (leaf)
Attributes (not on tree)
Comment (leaf)
Unknown (leaf)
A Decleration contains: Attributes (not on tree)
@endverbatim
*/
class TiXmlBase
{
friend class TiXmlNode;
friend class TiXmlElement;
friend class TiXmlDocument;
public:
TiXmlBase() {}
virtual ~TiXmlBase() {}
/* All TinyXml classes can print themselves to a filestream.
*/
virtual void Print( FILE* fp, int depth ) = 0;
protected:
/* General parsing helper method. Takes a pointer in,
skips all the white space it finds, and returns a pointer
to the first non-whitespace data.
*/
static const char* SkipWhiteSpace( const char* p );
/* Reads an XML name into the string provided. Returns
a pointer just past the last character of the name,
or 0 if the function has an error.
*/
static const char* ReadName( const char* p, std::string* name );
enum
{
TIXML_NO_ERROR = 0,
TIXML_ERROR_OPENING_FILE,
TIXML_ERROR_OUT_OF_MEMORY,
TIXML_ERROR_PARSING_ELEMENT,
TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME,
TIXML_ERROR_READING_ELEMENT_VALUE,
TIXML_ERROR_READING_ATTRIBUTES,
TIXML_ERROR_PARSING_EMPTY,
TIXML_ERROR_READING_END_TAG,
TIXML_ERROR_PARSING_UNKNOWN,
TIXML_ERROR_PARSING_COMMENT,
TIXML_ERROR_PARSING_DECLARATION,
TIXML_ERROR_STRING_COUNT
};
static const char* errorString[ TIXML_ERROR_STRING_COUNT ];
};
/** The parent class for everything in the Document Object Model.
(Except for attributes, which are contained in elements.)
Nodes have siblings, a parent, and children. A node can be
in a document, or stand on its own. The type of a TyXmlNode
can be queried, and it can be cast to its more defined type.
*/
class TiXmlNode : public TiXmlBase
{
public:
/** The types of XML nodes supported by TinyXml. (All the
unsupported types are picked up by UNKNOWN.)
*/
enum NodeType
{
DOCUMENT, ELEMENT, COMMENT, UNKNOWN, TEXT, DECLARATION, TYPECOUNT
};
virtual ~TiXmlNode();
/** The meaning of 'value' changes for the specific type of
TiXmlNode.
@verbatim
Document: filename of the xml file
Element: name of the element
Comment: the comment text
Unknown: the tag contents
Text: the text string
@endverbatim
The subclasses will wrap this function.
*/
const std::string& Value() const { return value; }
/** Changes the value of the node. Defined as:
@verbatim
Document: filename of the xml file
Element: name of the element
Comment: the comment text
Unknown: the tag contents
Text: the text string
@endverbatim
*/
void SetValue( const std::string& _value ) { value = _value; }
/// Delete all the children of this node. Does not affect 'this'.
void Clear();
/// One step up the DOM.
TiXmlNode* Parent() const { return parent; }
TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children.
TiXmlNode* FirstChild( const std::string& value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found.
TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children.
TiXmlNode* LastChild( const std::string& value ) const; /// The last child of this node matching 'value'. Will be null if there are no children.
/** An alternate way to walk the children of a node.
One way to iterate over nodes is:
@verbatim
for( child = parent->FirstChild(); child; child = child->NextSibling() )
@endverbatim
IterateChildren does the same thing with the syntax:
@verbatim
child = 0;
while( child = parent->IterateChildren( child ) )
@endverbatim
IterateChildren takes the previous child as input and finds
the next one. If the previous child is null, it returns the
first. IterateChildren will return null when done.
*/
TiXmlNode* IterateChildren( TiXmlNode* previous );
/// This flavor of IterateChildren searches for children with a particular 'value'
TiXmlNode* IterateChildren( const std::string& value, TiXmlNode* previous );
/** Add a new node related to this. Adds a child past the LastChild.
Returns a pointer to the new object or NULL if an error occured.
*/
TiXmlNode* InsertEndChild( const TiXmlNode& addThis );
/** Add a new node related to this. Adds a child before the specified child.
Returns a pointer to the new object or NULL if an error occured.
*/
TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis );
/** Add a new node related to this. Adds a child after the specified child.
Returns a pointer to the new object or NULL if an error occured.
*/
TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis );
/** Replace a child of this node.
Returns a pointer to the new object or NULL if an error occured.
*/
TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis );
/// Delete a child of this node.
bool RemoveChild( TiXmlNode* removeThis );
/// Navigate to a sibling node.
TiXmlNode* PreviousSibling() const { return prev; }
/// Navigate to a sibling node.
TiXmlNode* PreviousSibling( const std::string& ) const;
/// Navigate to a sibling node.
TiXmlNode* NextSibling() const { return next; }
/// Navigate to a sibling node with the given 'value'.
TiXmlNode* NextSibling( const std::string& ) const;
/** Convenience function to get through elements.
Calls NextSibling and ToElement. Will skip all non-Element
nodes. Returns 0 if there is not another element.
*/
TiXmlElement* NextSiblingElement() const;
/** Convenience function to get through elements.
Calls NextSibling and ToElement. Will skip all non-Element
nodes. Returns 0 if there is not another element.
*/
TiXmlElement* NextSiblingElement( const std::string& ) const;
/// Convenience function to get through elements.
TiXmlElement* FirstChildElement() const;
/// Convenience function to get through elements.
TiXmlElement* FirstChildElement( const std::string& value ) const;
/// Query the type (as an enumerated value, above) of this node.
virtual int Type() { return type; }
/** Return a pointer to the Document this node lives in.
Returns null if not in a document.
*/
TiXmlDocument* GetDocument() const;
TiXmlDocument* ToDocument() const { return ( type == DOCUMENT ) ? (TiXmlDocument*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
TiXmlElement* ToElement() const { return ( type == ELEMENT ) ? (TiXmlElement*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
TiXmlComment* ToComment() const { return ( type == COMMENT ) ? (TiXmlComment*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
TiXmlUnknown* ToUnknown() const { return ( type == UNKNOWN ) ? (TiXmlUnknown*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
TiXmlText* ToText() const { return ( type == TEXT ) ? (TiXmlText*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
TiXmlDeclaration* ToDeclaration() const { return ( type == DECLARATION ) ? (TiXmlDeclaration*) this : 0; } ///< Cast to a more defined type. Will return null not of the requested type.
virtual TiXmlNode* Clone() const = 0;
protected:
TiXmlNode( NodeType type );
virtual const char* Parse( const char* ) = 0;
// The node is passed in by ownership. This object will delete it.
TiXmlNode* LinkEndChild( TiXmlNode* addThis );
// Figure out what is at *p, and parse it. Return a node if
// successful, and update p.
TiXmlNode* IdentifyAndParse( const char** p );
void CopyToClone( TiXmlNode* target ) const { target->value = value; }
TiXmlNode* parent;
NodeType type;
TiXmlNode* firstChild;
TiXmlNode* lastChild;
std::string value;
TiXmlNode* prev;
TiXmlNode* next;
};
/** An attribute is a name-value pair. Elements have an arbitrary
number of attributes, each with a unique name.
@note The attributes are not TiXmlNodes, since they are not
part of the tinyXML document object model. There are other
suggested ways to look at this problem.
@note Attributes have a parent
*/
class TiXmlAttribute : public TiXmlBase
{
friend class TiXmlAttributeSet;
public:
/// Construct an empty attribute.
TiXmlAttribute() : prev( 0 ), next( 0 ) {}
/// Construct an attribute with a name and value.
TiXmlAttribute( const std::string& _name, const std::string& _value ) : name( _name ), value( _value ), prev( 0 ), next( 0 ) {}
const std::string& Name() const { return name; } ///< Return the name of this attribute.
const std::string& Value() const { return value; } ///< Return the value of this attribute.
void SetName( const std::string& _name ) { name = _name; } ///< Set the name of this attribute.
void SetValue( const std::string& _value ) { value = _value; } ///< Set the value.
/// Get the next sibling attribute in the DOM. Returns null at end.
TiXmlAttribute* Next();
/// Get the previous sibling attribute in the DOM. Returns null at beginning.
TiXmlAttribute* Previous();
bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; }
bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; }
bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; }
/* [internal use]
Attribtue parsing starts: first letter of the name
returns: the next char after the value end quote
*/
const char* Parse( const char* );
// [internal use]
virtual void Print( FILE* fp, int depth );
// [internal use]
// Set the document pointer so the attribute can report errors.
void SetDocument( TiXmlDocument* doc ) { document = doc; }
private:
TiXmlDocument* document; // A pointer back to a document, for error reporting.
std::string name;
std::string value;
TiXmlAttribute* prev;
TiXmlAttribute* next;
};
/* A class used to manage a group of attributes.
It is only used internally, both by the ELEMENT and the DECLARATION.
The set can be changed transparent to the Element and Declaration
classes that use it, but NOT transparent to the Attribute
which has to implement a next() and previous() method. Which makes
it a bit problematic and prevents the use of STL.
This version is implemented with circular lists because:
- I like circular lists
- it demonstrates some independence from the (typical) doubly linked list.
*/
class TiXmlAttributeSet
{
public:
TiXmlAttributeSet();
~TiXmlAttributeSet();
void Add( TiXmlAttribute* attribute );
void Remove( TiXmlAttribute* attribute );
TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; }
TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; }
TiXmlAttribute* Find( const std::string& name ) const;
private:
TiXmlAttribute sentinel;
};
/** The element is a container class. It has a value, the element name,
and can contain other elements, text, comments, and unknowns.
Elements also contain an arbitrary number of attributes.
*/
class TiXmlElement : public TiXmlNode
{
public:
/// Construct an element.
TiXmlElement( const std::string& value );
virtual ~TiXmlElement();
/** Given an attribute name, attribute returns the value
for the attribute of that name, or null if none exists.
*/
const std::string* Attribute( const std::string& name ) const;
/** Given an attribute name, attribute returns the value
for the attribute of that name, or null if none exists.
*/
const std::string* Attribute( const std::string& name, int* i ) const;
/** Sets an attribute of name to a given value. The attribute
will be created if it does not exist, or changed if it does.
*/
void SetAttribute( const std::string& name,
const std::string& value );
/** Sets an attribute of name to a given value. The attribute
will be created if it does not exist, or changed if it does.
*/
void SetAttribute( const std::string& name,
int value );
/** Deletes an attribute with the given name.
*/
void RemoveAttribute( const std::string& name );
TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } ///< Access the first attribute in this element.
TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } ///< Access the last attribute in this element.
// [internal use] Creates a new Element and returs it.
virtual TiXmlNode* Clone() const;
// [internal use]
virtual void Print( FILE* fp, int depth );
protected:
/* [internal use]
Attribtue parsing starts: next char past '<'
returns: next char past '>'
*/
virtual const char* Parse( const char* );
const char* ReadValue( const char* p );
private:
TiXmlAttributeSet attributeSet;
};
/** An XML comment.
*/
class TiXmlComment : public TiXmlNode
{
public:
/// Constructs an empty comment.
TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {}
virtual ~TiXmlComment() {}
// [internal use] Creates a new Element and returs it.
virtual TiXmlNode* Clone() const;
// [internal use]
virtual void Print( FILE* fp, int depth );
protected:
/* [internal use]
Attribtue parsing starts: at the ! of the !--
returns: next char past '>'
*/
virtual const char* Parse( const char* );
};
/** XML text. Contained in an element.
*/
class TiXmlText : public TiXmlNode
{
public:
TiXmlText() : TiXmlNode( TiXmlNode::TEXT ) {}
virtual ~TiXmlText() {}
// [internal use] Creates a new Element and returns it.
virtual TiXmlNode* Clone() const;
// [internal use]
virtual void Print( FILE* fp, int depth );
// [internal use]
bool Blank(); // returns true if all white space and new lines
/* [internal use]
Attribtue parsing starts: First char of the text
returns: next char past '>'
*/
virtual const char* Parse( const char* );
};
/** In correct XML the declaration is the first entry in the file.
@verbatim
<?xml version="1.0" standalone="yes"?>
@endverbatim
TinyXml will happily read or write files without a declaration,
however. There are 3 possible attributes to the declaration:
version, encoding, and standalone.
Note: In this version of the code, the attributes are
handled as special cases, not generic attributes, simply
because there can only be at most 3 and they are always the same.
*/
class TiXmlDeclaration : public TiXmlNode
{
public:
/// Construct an empty declaration.
TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {}
/// Construct.
TiXmlDeclaration( const std::string& version,
const std::string& encoding,
const std::string& standalone );
virtual ~TiXmlDeclaration() {}
/// Version. Will return empty if none was found.
const std::string& Version() { return version; }
/// Encoding. Will return empty if none was found.
const std::string& Encoding() { return encoding; }
/// Is this a standalone document?
const std::string& Standalone() { return standalone; }
// [internal use] Creates a new Element and returs it.
virtual TiXmlNode* Clone() const;
// [internal use]
virtual void Print( FILE* fp, int depth );
protected:
// [internal use]
// Attribtue parsing starts: next char past '<'
// returns: next char past '>'
virtual const char* Parse( const char* );
private:
std::string version;
std::string encoding;
std::string standalone;
};
/** Any tag that tinyXml doesn't recognize is save as an
unknown. It is a tag of text, but should not be modified.
It will be written back to the XML, unchanged, when the file
is saved.
*/
class TiXmlUnknown : public TiXmlNode
{
public:
TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {}
virtual ~TiXmlUnknown() {}
// [internal use]
virtual TiXmlNode* Clone() const;
// [internal use]
virtual void Print( FILE* fp, int depth );
protected:
/* [internal use]
Attribute parsing starts: First char of the text
returns: next char past '>'
*/
virtual const char* Parse( const char* );
};
/** Always the top level node. A document binds together all the
XML pieces. It can be saved, loaded, and printed to the screen.
The 'value' of a document node is the xml file name.
*/
class TiXmlDocument : public TiXmlNode
{
public:
/// Create an empty document, that has no name.
TiXmlDocument();
/// Create a document with a name. The name of the document is also the filename of the xml.
TiXmlDocument( const std::string& documentName );
virtual ~TiXmlDocument() {}
/** Load a file using the current document value.
Returns true if successful. Will delete any existing
document data before loading.
*/
bool LoadFile();
/// Save a file using the current document value. Returns true if successful.
bool SaveFile();
/// Load a file using the given filename. Returns true if successful.
bool LoadFile( const std::string& filename );
/// Save a file using the given filename. Returns true if successful.
bool SaveFile( const std::string& filename );
/// Parse the given null terminated block of xml data.
const char* Parse( const char* );
/// If, during parsing, a error occurs, Error will be set to true.
bool Error() { return error; }
/// Contains a textual (english) description of the error if one occurs.
const std::string& ErrorDesc() { return errorDesc; }
/// Write the document to a file -- usually invoked by SaveFile.
virtual void Print( FILE* fp, int depth = 0 );
/// Dump the document to standard out.
void Print() { Print( stdout, 0 ); }
// [internal use]
virtual TiXmlNode* Clone() const;
// [internal use]
void SetError( int err ) { assert( err > 0 && err < TIXML_ERROR_STRING_COUNT );
error = true;
errorId = err;
errorDesc = errorString[ errorId ]; }
private:
bool error;
int errorId;
std::string errorDesc;
};
#endif

View File

@@ -0,0 +1,24 @@
#include "tinyxml.h"
// The goal of the seperate error file is to make the first
// step towards localization. tinyxml (currently) only supports
// latin-1, but at least the error messages could now be translated.
//
// It also cleans up the code a bit.
const char* TiXmlBase::errorString[ TIXML_ERROR_STRING_COUNT ] =
{
"No error",
"Failed to open file",
"Memory allocation failed.",
"Error parsing Element.",
"Failed to read Element name",
"Error reading Element value.",
"Error reading Attributes.",
"Error: empty tag.",
"Error reading end tag.",
"Error parsing Unknown.",
"Error parsing Comment.",
"Error parsing Declaration.",
};

View File

@@ -0,0 +1,535 @@
/*
Copyright (c) 2000 Lee Thomason (www.grinninglizard.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include "tinyxml.h"
#include <ctype.h>
const char* TiXmlBase::SkipWhiteSpace( const char* p )
{
while ( p && *p &&
( isspace( *p ) || *p == '\n' || *p == '\r' ) )
p++;
return p;
}
const char* TiXmlBase::ReadName( const char* p, std::string* name )
{
*name = "";
const char* start = p;
// Names start with letters or underscores.
// After that, they can be letters, underscores, numbers,
// hyphens, or colons. (Colons are valid ony for namespaces,
// but tinyxml can't tell namespaces from names.)
if ( p && ( isalpha( *p ) || *p == '_' ) )
{
p++;
while( p && *p &&
( isalnum( *p )
|| *p == '_'
|| *p == '-'
|| *p == ':' ) )
{
p++;
}
name->append( start, p - start );
return p;
}
return 0;
}
const char* TiXmlDocument::Parse( const char* start )
{
// Parse away, at the document level. Since a document
// contains nothing but other tags, most of what happens
// here is skipping white space.
const char* p = start;
p = SkipWhiteSpace( p );
if ( !p || !*p )
{
error = true;
errorDesc = "Document empty.";
}
while ( p && *p )
{
if ( *p != '<' )
{
error = true;
errorDesc = "The '<' symbol that starts a tag was not found.";
break;
}
else
{
TiXmlNode* node = IdentifyAndParse( &p );
if ( node )
{
LinkEndChild( node );
}
}
p = SkipWhiteSpace( p );
}
return 0; // Return null is fine for a document: once it is read, the parsing is over.
}
TiXmlNode* TiXmlNode::IdentifyAndParse( const char** where )
{
const char* p = *where;
TiXmlNode* returnNode = 0;
assert( *p == '<' );
TiXmlDocument* doc = GetDocument();
p = SkipWhiteSpace( p+1 );
// What is this thing?
// - Elements start with a letter or underscore, but xml is reserved.
// - Comments: <!--
// - Everthing else is unknown to tinyxml.
//
if ( tolower( *(p+0) ) == '?'
&& tolower( *(p+1) ) == 'x'
&& tolower( *(p+2) ) == 'm'
&& tolower( *(p+3) ) == 'l' )
{
#ifdef DEBUG_PARSER
printf( "XML parsing Declaration\n" );
#endif
returnNode = new TiXmlDeclaration();
}
else if ( isalpha( *p ) || *p == '_' )
{
#ifdef DEBUG_PARSER
printf( "XML parsing Element\n" );
#endif
returnNode = new TiXmlElement( "" );
}
else if ( *(p+0) == '!'
&& *(p+1) == '-'
&& *(p+2) == '-' )
{
#ifdef DEBUG_PARSER
printf( "XML parsing Comment\n" );
#endif
returnNode = new TiXmlComment();
}
else
{
#ifdef DEBUG_PARSER
printf( "XML parsing Comment\n" );
#endif
returnNode = new TiXmlUnknown();
}
if ( returnNode )
{
// Set the parent, so it can report errors
returnNode->parent = this;
p = returnNode->Parse( p );
}
else
{
if ( doc )
doc->SetError( TIXML_ERROR_OUT_OF_MEMORY );
p = 0;
}
*where = p;
return returnNode;
}
const char* TiXmlElement::Parse( const char* p )
{
TiXmlDocument* document = GetDocument();
p = SkipWhiteSpace( p );
if ( !p || !*p )
{
if ( document ) document->SetError( TIXML_ERROR_PARSING_ELEMENT );
return 0;
}
// Read the name.
p = ReadName( p, &value );
if ( !p )
{
if ( document ) document->SetError( TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME );
return 0;
}
std::string endTag = "</";
endTag += value;
endTag += ">";
// Check for and read attributes. Also look for an empty
// tag or an end tag.
while ( p && *p )
{
p = SkipWhiteSpace( p );
if ( !p || !*p )
{
if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
return 0;
}
if ( *p == '/' )
{
// Empty tag.
if ( *(p+1) != '>' )
{
if ( document ) document->SetError( TIXML_ERROR_PARSING_EMPTY );
return 0;
}
return p+2;
}
else if ( *p == '>' )
{
// Done with attributes (if there were any.)
// Read the value -- which can include other
// elements -- read the end tag, and return.
p = ReadValue( p+1 ); // Note this is an Element method, and will set the error if one happens.
if ( !p )
return 0;
// We should find the end tag now
std::string buf( p, endTag.size() );
if ( endTag == buf )
{
return p+endTag.size();
}
else
{
if ( document ) document->SetError( TIXML_ERROR_READING_END_TAG );
return 0;
}
}
else
{
// Try to read an element:
TiXmlAttribute attrib;
attrib.SetDocument( document );
p = attrib.Parse( p );
if ( p )
{
SetAttribute( attrib.Name(), attrib.Value() );
}
}
}
return 0;
}
const char* TiXmlElement::ReadValue( const char* p )
{
TiXmlDocument* document = GetDocument();
// Read in text and elements in any order.
p = SkipWhiteSpace( p );
while ( p && *p )
{
const char* start = p;
while ( *p && *p != '<' )
p++;
if ( !*p )
{
if ( document ) document->SetError( TIXML_ERROR_READING_ELEMENT_VALUE );
return 0;
}
if ( p != start )
{
// Take what we have, make a text element.
TiXmlText* text = new TiXmlText();
if ( !text )
{
if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY );
return 0;
}
text->Parse( start );
if ( !text->Blank() )
LinkEndChild( text );
else
delete text;
}
else
{
// We hit a '<'
// Have we hit a new element or an end tag?
if ( *(p+1) == '/' )
{
return p; // end tag
}
else
{
// TiXmlElement* element = new TiXmlElement( "" );
//
// if ( element )
// {
// p = element->Parse( p+1 );
// if ( p )
// LinkEndChild( element );
// }
// else
// {
// if ( document ) document->SetError( ERROR_OUT_OF_MEMORY );
// return 0;
// }
TiXmlNode* node = IdentifyAndParse( &p );
if ( node )
{
LinkEndChild( node );
}
else
{
return 0;
}
}
}
}
return 0;
}
const char* TiXmlUnknown::Parse( const char* p )
{
const char* end = strchr( p, '>' );
if ( !end )
{
TiXmlDocument* document = GetDocument();
if ( document )
document->SetError( TIXML_ERROR_PARSING_UNKNOWN );
return 0;
}
else
{
value = std::string( p, end-p );
// value.resize( end - p );
return end + 1; // return just past the '>'
}
}
const char* TiXmlComment::Parse( const char* p )
{
assert( *p == '!' && *(p+1) == '-' && *(p+2) == '-' );
// Find the end, copy the parts between to the value of
// this object, and return.
const char* start = p+3;
const char* end = strstr( p, "-->" );
if ( !end )
{
TiXmlDocument* document = GetDocument();
if ( document )
document->SetError( TIXML_ERROR_PARSING_COMMENT );
return 0;
}
else
{
// Assemble the comment, removing the white space.
bool whiteSpace = false;
const char* q;
for( q=start; q<end; q++ )
{
if ( isspace( *q ) )
{
if ( !whiteSpace )
{
value += ' ';
whiteSpace = true;
}
}
else
{
value += *q;
whiteSpace = false;
}
}
// value = std::string( start, end-start );
return end + 3; // return just past the '>'
}
}
const char* TiXmlAttribute::Parse( const char* p )
{
// Read the name, the '=' and the value.
p = ReadName( p, &name );
if ( !p )
{
if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
return 0;
}
p = SkipWhiteSpace( p );
if ( !p || *p != '=' )
{
if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
return 0;
}
p = SkipWhiteSpace( p+1 );
if ( !p || !*p )
{
if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES );
return 0;
}
const char* end = 0;
const char* start = p+1;
const char* past = 0;
if ( *p == '\'' )
{
end = strchr( start, '\'' );
past = end+1;
}
else if ( *p == '"' )
{
end = strchr( start, '"' );
past = end+1;
}
else
{
// All attribute values should be in single or double quotes.
// But this is such a common error that the parser will try
// its best, even without them.
start--;
for ( end = start; *end; end++ )
{
if ( isspace( *end ) || *end == '/' || *end == '>' )
break;
}
past = end;
}
value = std::string( start, end-start );
return past;
}
const char* TiXmlText::Parse( const char* p )
{
value = "";
bool whitespace = false;
// Remove leading white space:
p = SkipWhiteSpace( p );
while ( *p && *p != '<' )
{
if ( *p == '\r' || *p == '\n' )
{
whitespace = true;
}
else if ( isspace( *p ) )
{
whitespace = true;
}
else
{
// If we've found whitespace, add it before the
// new character. Any whitespace just becomes a space.
if ( whitespace )
{
value += ' ';
whitespace = false;
}
value += *p;
}
p++;
}
// Keep white space before the '<'
if ( whitespace )
value += ' ';
return p;
}
const char* TiXmlDeclaration::Parse( const char* p )
{
// Find the beginning, find the end, and look for
// the stuff in-between.
const char* start = p+4;
const char* end = strstr( start, "?>" );
// Be nice to the user:
if ( !end )
{
end = strstr( start, ">" );
end++;
}
else
{
end += 2;
}
if ( !end )
{
TiXmlDocument* document = GetDocument();
if ( document )
document->SetError( TIXML_ERROR_PARSING_DECLARATION );
return 0;
}
else
{
const char* p;
p = strstr( start, "version" );
if ( p && p < end )
{
TiXmlAttribute attrib;
attrib.Parse( p );
version = attrib.Value();
}
p = strstr( start, "encoding" );
if ( p && p < end )
{
TiXmlAttribute attrib;
attrib.Parse( p );
encoding = attrib.Value();
}
p = strstr( start, "standalone" );
if ( p && p < end )
{
TiXmlAttribute attrib;
attrib.Parse( p );
standalone = attrib.Value();
}
}
return end;
}
bool TiXmlText::Blank()
{
for ( unsigned i=0; i<value.size(); i++ )
if ( !isspace( value[i] ) )
return false;
return true;
}

View File

@@ -0,0 +1,865 @@
#include "xmlgui.h"
#include <stdio.h>
#include <stdlib.h>
XmlGui::XmlGui()
{
}
bool XmlGui::parse(const std::string &filename)
{
TiXmlElement *element = NULL;
TiXmlNode *node = NULL;
doc = new TiXmlDocument(filename.c_str());
bool loadOkay = doc->LoadFile();
if ( !loadOkay )
{
throw GCN_EXCEPTION("Error parsing xml file.");
}
node = doc->FirstChild();
if(node == NULL)
{
throw GCN_EXCEPTION("Xml document is null or has errors.");
}
while(node!=NULL)
{
element = node->ToElement();
parseWidgets(element,NULL);
node = doc->IterateChildren(node);
}
return true;
}
void XmlGui::addToParent(gcn::Widget *widget,gcn::Widget *parent)
{
if(!parent) return;
gcn::Container* top = dynamic_cast<gcn::Container *>(parent);
if(top)
{
top->add(widget);
}
else
{
gcn::Window* window = dynamic_cast<gcn::Window *>(parent);
if(window)
// window->setContent(widget);
window->add(widget);
else
{
gcn::ScrollArea* scrollarea = dynamic_cast<gcn::ScrollArea *>(parent);
scrollarea->setContent(widget);
}
}
}
void XmlGui::parseWidgets(TiXmlElement *element, gcn::Widget *parent)
{
if(!element) return;
std::string value = element->Value();
if(value == "container")
parseContainer(element,parent);
if(value == "label")
parseLabel(element,parent);
else if(value == "radiobutton")
parseRadioButton(element,parent);
else if(value == "button")
parseButton(element,parent);
else if(value == "checkbox")
parseCheckBox(element,parent);
else if(value == "icon")
parseIcon(element,parent);
else if(value == "textbox")
parseTextBox(element,parent);
else if(value == "textfield")
parseTextField(element,parent);
else if(value == "slider")
parseSlider(element,parent);
else if(value == "window")
parseWindow(element,parent);
else if(value == "scrollarea")
parseScrollArea(element,parent);
else if(value == "dropdown")
parseDropdown(element,parent);
else if(value == "listbox")
parseListbox(element,parent);
}
void XmlGui::parseDefaults(TiXmlElement *element, gcn::Widget *widget)
{
if(!element) return;
if(element->Attribute("x"))
{
int x = atoi(element->Attribute("x")->c_str());
widget->setX(x);
}
if(element->Attribute("y"))
{
int y = atoi(element->Attribute("y")->c_str());
widget->setY(y);
}
if(element->Attribute("width"))
{
int w = atoi(element->Attribute("width")->c_str());
widget->setWidth(w);
}
if(element->Attribute("height"))
{
int h = atoi(element->Attribute("height")->c_str());
widget->setHeight(h);
}
if(element->Attribute("basecolor"))
{
int color;
sscanf(element->Attribute("basecolor")->c_str(),"%x",&color);
widget->setBaseColor(gcn::Color(color));
}
if(element->Attribute("foregroundcolor"))
{
int color;
sscanf(element->Attribute("foregroundcolor")->c_str(),"%x",&color);
widget->setForegroundColor(gcn::Color(color));
}
if(element->Attribute("backgroundcolor"))
{
int color;
sscanf(element->Attribute("backgroundcolor")->c_str(),"%x",&color);
widget->setBackgroundColor(gcn::Color(color));
}
if(element->Attribute("frame"))
{
int b = atoi(element->Attribute("framesize")->c_str());
widget->setFrameSize(b);
}
if(element->Attribute("font"))
{
if(fonts[*element->Attribute("font")])
widget->setFont(fonts[*element->Attribute("visible")]);
}
if(element->Attribute("visible"))
widget->setVisible(checkBool(*element->Attribute("visible")));
if(element->Attribute("focusable"))
widget->setFocusable(checkBool(*element->Attribute("focusable")));
if(element->Attribute("enabled"))
widget->setEnabled(checkBool(*element->Attribute("enabled")));
if(element->Attribute("tabin"))
widget->setTabInEnabled(checkBool(*element->Attribute("tabin")));
if(element->Attribute("tabout"))
widget->setTabOutEnabled(checkBool(*element->Attribute("tabout")));
if(element->Attribute("eventId"))
widget->setActionEventId(*element->Attribute("eventId"));
if(element->Attribute("actionListener"))
widget->addActionListener(actions[*element->Attribute("actionListener")]);
}
void XmlGui::parseContainer(TiXmlElement *element, gcn::Widget *parent)
{
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("Container Widget must have a unique name");
}
gcn::Container *c = new gcn::Container();
if(element->Attribute("opaque"))
c->setOpaque(checkBool(*element->Attribute("opaque")));
parseDefaults(element,c);
//parsing child elements
TiXmlNode *child = element->FirstChild();
if(child)
{
while(child)
{
TiXmlElement *e = child->ToElement();
parseWidgets(e,c);
child = doc->IterateChildren(child);
}
}
addToParent(c,parent);
widgets[name] = c;
}
void XmlGui::parseLabel(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = *element->Attribute("name");
}else
{
throw GCN_EXCEPTION("Label Widget must have a unique name");
}
gcn::Label *label = new gcn::Label;
if(element->Attribute("caption"))
{
label->setCaption(*element->Attribute("caption"));
}
label->adjustSize();
if(element->Attribute("align"))
{
if(*element->Attribute("align") == "center" || *element->Attribute("align") == "CENTER")
{
label->setAlignment(gcn::Graphics::CENTER);
}else if(*element->Attribute("align") == "left" || *element->Attribute("align") == "LEFT")
{
label->setAlignment(gcn::Graphics::LEFT);
}else
{
label->setAlignment(gcn::Graphics::RIGHT);
}
}
parseDefaults(element,label);
addToParent(label,parent);
widgets[name] = label;
}
void XmlGui::parseButton(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("Button Widget must have a unique name");
}
gcn::Button *button = new gcn::Button;
if(element->Attribute("caption"))
{
button->setCaption(*element->Attribute("caption"));
}
if(element->Attribute("align"))
{
if(*element->Attribute("align") == "center" || *element->Attribute("align") == "CENTER")
{
button->setAlignment(gcn::Graphics::CENTER);
}else if(*element->Attribute("align") == "left" || *element->Attribute("align") == "LEFT")
{
button->setAlignment(gcn::Graphics::LEFT);
}else
{
button->setAlignment(gcn::Graphics::RIGHT);
}
}
button->adjustSize();
parseDefaults(element,button);
// button->lostFocus(); //fix: this call must't exists
//?????
addToParent(button,parent);
widgets[name] = button;
}
void XmlGui::parseCheckBox(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("Checkbox Widget must have a unique name");
}
gcn::CheckBox *checkbox = new gcn::CheckBox;
if(element->Attribute("caption"))
{
checkbox->setCaption(*element->Attribute("caption"));
}
checkbox->adjustSize();
if(element->Attribute("selected"))
checkbox->setSelected(checkBool(*element->Attribute("selected")));
parseDefaults(element,checkbox);
addToParent(checkbox,parent);
widgets[name] = checkbox;
}
void XmlGui::parseRadioButton(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("RadioButton Widget must have a unique name");
}
gcn::RadioButton *radio = new gcn::RadioButton;
if(element->Attribute("caption"))
{
radio->setCaption(*element->Attribute("caption"));
}
radio->adjustSize();
if(element->Attribute("selected"))
radio->setSelected(checkBool(*element->Attribute("selected")));
if(element->Attribute("group"))
radio->setGroup(*element->Attribute("group"));
parseDefaults(element,radio);
addToParent(radio,parent);
widgets[name] = radio;
}
void XmlGui::parseIcon(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("Icon Widget must have a unique name");
}
gcn::Icon *icon;
gcn::Image *image;
if(element->Attribute("image"))
{
// image = new gcn::Image(*element->Attribute("image"));
image = gcn::Image::load(*element->Attribute("image"));
}
if(image)
{
icon = new gcn::Icon(image);
}
parseDefaults(element,icon);
addToParent(icon,parent);
widgets[name] = icon;
}
void XmlGui::parseTextBox(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("TextBox Widget must have a unique name");
}
gcn::TextBox *textbox = new gcn::TextBox;
if(element->Attribute("editable"))
textbox->setEditable(checkBool(*element->Attribute("editable")));
if(element->Attribute("text"))
{
textbox->setText(*element->Attribute("text"));
}
if(element->Attribute("opaque"))
textbox->setOpaque(checkBool(*element->Attribute("opaque")));
parseDefaults(element,textbox);
addToParent(textbox,parent);
widgets[name] = textbox;
}
void XmlGui::parseTextField(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("TextField Widget must have a unique name");
}
gcn::TextField *textfield = new gcn::TextField;
if(element->Attribute("text"))
{
textfield->setText(*element->Attribute("text"));
}
parseDefaults(element,textfield);
addToParent(textfield,parent);
widgets[name] = textfield;
}
void XmlGui::parseSlider(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("Slider Widget must have a unique name");
}
gcn::Slider *slider = new gcn::Slider;
if(element->Attribute("start"))
{
int start = atoi(element->Attribute("start")->c_str());
slider->setScaleStart(start);
}
if(element->Attribute("end"))
{
int end = atoi(element->Attribute("end")->c_str());
slider->setScaleEnd(end);
}
if(element->Attribute("value"))
{
int value = atoi(element->Attribute("value")->c_str());
slider->setValue(value);
}
if(element->Attribute("markerLength"))
{
int l = atoi(element->Attribute("markerLength")->c_str());
slider->setMarkerLength(l);
}
if(element->Attribute("stepLength"))
{
int l = atoi(element->Attribute("stepLength")->c_str());
slider->setStepLength(l);
}
if(element->Attribute("orientation"))
{
if(*element->Attribute("orientation") == "HORIZONTAL" || *element->Attribute("orientation") == "horizontal")
slider->setOrientation(gcn::Slider::HORIZONTAL);
else slider->setOrientation(gcn::Slider::VERTICAL);
}
parseDefaults(element,slider);
addToParent(slider,parent);
widgets[name] = slider;
}
void XmlGui::parseWindow(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = *element->Attribute("name");
}else
{
throw GCN_EXCEPTION("Window Widget must have a unique name");
}
gcn::Window *window = new gcn::Window;
if(element->Attribute("caption"))
{
window->setCaption(*element->Attribute("caption"));
}
if(element->Attribute("tabbing"))
{
window->setPadding(checkBool(*element->Attribute("tabbing")));
}
if(element->Attribute("movable"))
{
window->setMovable(checkBool(*element->Attribute("movable")));
}
if(element->Attribute("titleBarHeight"))
{
int h = atoi(element->Attribute("titleBarHeight")->c_str());
window->setTitleBarHeight(h);
}
if(element->Attribute("opaque"))
window->setOpaque(checkBool(*element->Attribute("opaque")));
parseDefaults(element,window);
//parsing child elements
TiXmlNode *child = element->FirstChild();
if(child)
{
while(child)
{
TiXmlElement *e = child->ToElement();
parseWidgets(e,window);
child = doc->IterateChildren(child);
}
}
window->resizeToContent();
addToParent(window,parent);
widgets[name] = window;
}
void XmlGui::parseScrollArea(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("ScrollArea Widget must have a unique name");
}
gcn::ScrollArea *scroll = new gcn::ScrollArea;
if(element->Attribute("hPolicy"))
{
if(*element->Attribute("hPolicy") == "ALWAYS" || *element->Attribute("hPolicy") == "always")
scroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS);
else if(*element->Attribute("hPolicy") == "NEVER" || *element->Attribute("hPolicy") == "never")
scroll->setHorizontalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
}
if(element->Attribute("vPolicy"))
{
if(*element->Attribute("vPolicy") == "ALWAYS" || *element->Attribute("vPolicy") == "always")
scroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_ALWAYS);
else if(*element->Attribute("vPolicy") == "NEVER" || *element->Attribute("vPolicy") == "never")
scroll->setVerticalScrollPolicy(gcn::ScrollArea::SHOW_NEVER);
}
if(element->Attribute("vScrollAmount"))
{
int h;
sscanf(element->Attribute("vScrollAmount")->c_str(),"%d",&h);
scroll->setVerticalScrollAmount(h);
}
if(element->Attribute("hScrollAmount"))
{
int h = atoi(element->Attribute("hScrollAmount")->c_str());
scroll->setHorizontalScrollAmount(h);
}
if(element->Attribute("scrollBarWidth"))
{
int w = atoi(element->Attribute("scrollbarWidth")->c_str());
scroll->setScrollbarWidth(w);
}
if(element->Attribute("content"))
{
gcn::Widget *content = getWidget(*element->Attribute("content"));
if(content)
{
scroll->setContent(content);
}
}
parseDefaults(element,scroll);
if(!scroll->getContent())
{
//parsing child elements
TiXmlNode *child = element->FirstChild();
if(child)
{
while(child)
{
TiXmlElement *e = child->ToElement();
parseWidgets(e,scroll);
child = doc->IterateChildren(child);
}
}
}
addToParent(scroll,parent);
widgets[name] = scroll;
}
void XmlGui::parseDropdown(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("DropDown Widget must have a unique name");
}
gcn::DropDown *dropdown = new gcn::DropDown;
parseDefaults(element,dropdown);
XmlListModel *listmodel;
//parsing child elements
TiXmlNode *child = element->FirstChild();
if(child)
{
listmodel = new XmlListModel;
while(child)
{
TiXmlElement *e = child->ToElement();
if(e->Value() == "li")
{
listmodel->items.push_back(e->FirstChild()->Value());
}
child = doc->IterateChildren(child);
}
}
if(listmodel)
dropdown->setListModel(listmodel);
if(element->Attribute("selected"))
{
int s = atoi(element->Attribute("selected")->c_str());
dropdown->setSelected(s);
}
addToParent(dropdown,parent);
widgets[name] = dropdown;
}
void XmlGui::parseListbox(TiXmlElement *element,gcn::Widget *parent)
{
if(!element)
return;
std::string name;
if(element->Attribute("name"))
{
name = element->Attribute("name")->c_str();
}else
{
throw GCN_EXCEPTION("ListBox Widget must have a unique name");
}
gcn::ListBox *listbox = new gcn::ListBox;
parseDefaults(element,listbox);
XmlListModel *listmodel;
//parsing child elements
TiXmlNode *child = element->FirstChild();
if(child)
{
listmodel = new XmlListModel;
while(child)
{
TiXmlElement *e = child->ToElement();
if(e->Value() == "li")
{
listmodel->items.push_back(e->FirstChild()->Value());
}
child = doc->IterateChildren(child);
}
}
if(listmodel)
listbox->setListModel(listmodel);
if(element->Attribute("selected"))
{
int s = atoi(element->Attribute("selected")->c_str());
listbox->setSelected(s);
}
addToParent(listbox,parent);
widgets[name] = listbox;
}
gcn::Widget *XmlGui::getWidget(const std::string &name)
{
std::map<std::string,gcn::Widget*>::iterator it = widgets.find(name);
if(it == widgets.end()) {
return NULL;
}
return widgets[name];
}
bool XmlGui::checkBool(const std::string &value)
{
return (value == "1" || value == "true" || value == "True");
}
void XmlGui::addActionListener(const std::string &name, gcn::ActionListener *al)
{
if(al)
actions[name] = al;
}
void XmlGui::addFont(const std::string &name, gcn::Font *font)
{
if(font)
fonts[name] = font;
}
int XmlListModel::getNumberOfElements()
{
return items.size();
}
std::string XmlListModel::getElementAt(int i)
{
return items[i];
}

View File

@@ -0,0 +1,155 @@
/* XmlGui - xml parsing class for guichan (http://guichan.sourceforge.net)
* author - quard (quard8@gmail.com)
* Changes:
* v. 0.4 - fixed bug in Visual Studio .NET 2003, when compiler option /GR is not enabled;
fixed widget allocation, when attribute "name" is't exists
deleted all "return false" after GCN_EXCEPTION, because they not used ever
* v. 0.3.5 - fixed stupid bug, when widgets not parsed if parent widget is NULL
* v. 0.3 - added parsing method for widget,
* now checking widget node is in one function
* v. 0.2 - small bug fix
* - added parsing widgets under 'container'
* - changed sscanf to atoi
* v. 0.1 - first public release
*/
#ifndef XML_GUI_H
#define XML_GUI_H
#include <guichan.hpp>
#include "tinyxml.h"
#include <map>
//!XmlGui class for loading gui widget from xml file
class XmlGui
{
public:
//!constructor
XmlGui();
//!parse xml file
//@param filename the file name to parse
//@return true if loaded ok
bool parse(const std::string &filename);
//@param name th widget name
//@return widget by name
gcn::Widget *getWidget(const std::string &name);
//!parse default parameters for all widgets
//@param element the xml element
//@param widget the current widget
void parseDefaults(TiXmlElement *element, gcn::Widget *widget);
//!parse container widget
//@param element the xml element
//@param widget the current widget
void parseContainer(TiXmlElement *element, gcn::Widget *parent);
//!parse label widget
//@param element the xml element
//@param widget the current widget
void parseLabel(TiXmlElement *element, gcn::Widget *parent);
//!parse button widget
//@param element the xml element
//@param widget the current widget
void parseButton(TiXmlElement *element, gcn::Widget *parent);
//!parse checkbox widget
//@param element the xml element
//@param widget the current widget
void parseCheckBox(TiXmlElement *element, gcn::Widget *parent);
//!parse radiobutton widget
//@param element the xml element
//@param widget the current widget
void parseRadioButton(TiXmlElement *element, gcn::Widget *parent);
//!parse icon widget
//@param element the xml element
//@param widget the current widget
void parseIcon(TiXmlElement *element, gcn::Widget *parent);
//!parse textbox widget
//@param element the xml element
//@param widget the current widget
void parseTextBox(TiXmlElement *element, gcn::Widget *parent);
//!parse textfield widget
//@param element the xml element
//@param widget the current widget
void parseTextField(TiXmlElement *element, gcn::Widget *parent);
//!parse slider widget
//@param element the xml element
//@param widget the current widget
void parseSlider(TiXmlElement *element, gcn::Widget *parent);
//!parse window widget
//@param element the xml element
//@param widget the current widget
void parseWindow(TiXmlElement *element, gcn::Widget *parent);
//!parse scrollarea widget
//@param element the xml element
//@param widget the current widget
void parseScrollArea(TiXmlElement *element,gcn::Widget *parent);
//!parse dropdown widget
//@param element the xml element
//@param widget the current widget
void parseDropdown(TiXmlElement *element,gcn::Widget *parent);
//!parse listbox widget
//@param element the xml element
//@param widget the current widget
void parseListbox(TiXmlElement *element,gcn::Widget *parent);
//!add actionlistener to array
//@param name the actionlistener name
//@param al the pointer to actionlistener class
void addActionListener(const std::string &name,gcn::ActionListener *al);
//!add font
//@param name the font name
//@param al the pointer to font class
void addFont(const std::string &name,gcn::Font *font);
private:
//!parse xml node
//@param element - xml element
//@param parent - the parent widget
void parseWidgets(TiXmlElement *element, gcn::Widget *parent);
//!adding widget to parent
//!parent widget can be Container,ScrollArea,Window. this function get class and set widget or add widget (for Container)
//@param widget our widget
//@param parent the parent widget
void addToParent(gcn::Widget *widget, gcn::Widget *parent);
//!check string value for boolean value
//@param value the string value
//@return true if value are "1" or "true"
bool checkBool(const std::string &value);
std::map<std::string,gcn::Widget*> widgets;
std::map<std::string,gcn::ActionListener*> actions;
std::map<std::string,gcn::Font*> fonts;
//temporary xml document (need by some functions)
TiXmlDocument *doc;
};
class XmlListModel : public gcn::ListModel
{
public:
virtual int getNumberOfElements();
virtual std::string getElementAt(int i);
std::vector<std::string> items;
};
#endif