Because of a recent discussion about wxWidgets and the ability to "skin" applications I reviewed one of my everlasting projects called wxSkin.
wxSkin is a set of controls that use images to "skin" them. Apart from creating each control and pass it a skin image, wxSkin features a central class called wxSkinEngine that automates most of the skinning by using a simple XML file as a skin definition and is able to load these files either from disk or out of a zip archive. wxSkinEngine parses these files and is able to assign skins to specific windows. Thus loading a different skin during runtime is possible and does not require to reload the application.
wxSkin has two basic top level windows.
wxSkinSimpleFrame is a frame that uses only one image for skinning. It can't be sized in a good way.
wxSkinFrame uses 4 borders, 4 window edges and a body to create the whole GUI. These frames can be sized.
Both frame classes offer support for working with sizers that can be added to special "client" areas.
Apart from these frame classes Buttons, Checkboxes, Gauges and Radiobuttons are implemented. What's still missing are sliders and some transparent static text controls, as well as some "convenience" controls like toggle buttons.
There still is work to do. Currently wxSkin controls only have two states, hovering and disabled states will be added soon. In addition to that the code needs some cleanup and a documentation needs to be written. The GTK port works to some extent, but there are minor issues with that.
Anyway, I decided to give you all a small glimpse of what skinning with wxWidgets might look like once I finished this. I created a small example application to demonstrate wxSkin. Guess what: It's a media player
Currently only two skins exist, both are modified skin from VLC to match wxSkins format. Credit for these skins go to the original authors.
Example skin 1:
Example skin 2:
Both skins use PNG files, but all formats wxWidgets is able to handle are supported.
If you want to try this example app for yourself you may download it here:
Note: This is a Windows binary only version! It uses wxMediaCtrl with Directshow. It comes with both skins and can change the skins during runtime by pressing a button (you'll find out which one Hint: It has something to do with "settings").
To see what the skin files look like, simply open the archives. I could have created a folde structure inside the archives, but I was to lazy
I added some comments in the skin files.
If you're curious how wxSkin works in the applications, here's some example code:
Code: Select all
//Get the skin engine, the master of process //load a skin file //a skin file is either a valid xml file //or a zip archive. archives may contain a folder structure for subgrouping elements wxSkinEngine::Get()->Load("skin.zip",true); //create a "simple" frame //a simple frame only uses one image as a skin //there are also "complex" frame that have 4 borders, 4 window edges and a body frame = new wxSkinSimpleFrame(NULL,-1,wxSkinEngine::Get()->GetSkinName()); media = new wxMediaCtrl(frame,-1,"",wxDefaultPosition,wxDefaultSize,0,wxMEDIABACKEND_DIRECTSHOW ); //create some buttons and a checkbox wxSkinButton* btnOpen = new wxSkinButton(frame,ID_OPEN); wxSkinButton* btnNext = new wxSkinButton(frame,ID_NEXT); wxSkinButton* btnPrev = new wxSkinButton(frame,ID_PREV); wxSkinButton* btnStop = new wxSkinButton(frame,ID_STOP); wxSkinButton* btnPlay = new wxSkinButton(frame,ID_PLAY); wxSkinButton* btnSup = new wxSkinButton(frame,ID_SUP); wxSkinButton* btnSdown = new wxSkinButton(frame,ID_SDOWN); wxSkinButton* btnPlist = new wxSkinButton(frame,ID_PLIST); wxSkinButton* btnPrefs = new wxSkinButton(frame,ID_PREFS); wxSkinCheckBox* chkMute = new wxSkinCheckBox(frame,ID_MUTE); //assigne the elements to skin with names used as identifiers in the skin file wxSkinEngine::Get()->AssignWindow("PlayerFrame",frame); wxSkinEngine::Get()->AssignWindow("button_open",btnOpen); wxSkinEngine::Get()->AssignWindow("button_next",btnNext); wxSkinEngine::Get()->AssignWindow("button_prev",btnPrev); wxSkinEngine::Get()->AssignWindow("button_stop",btnStop); wxSkinEngine::Get()->AssignWindow("button_play",btnPlay); wxSkinEngine::Get()->AssignWindow("button_speedup",btnSup); wxSkinEngine::Get()->AssignWindow("button_speeddown",btnSdown); wxSkinEngine::Get()->AssignWindow("button_playlist",btnPlist); wxSkinEngine::Get()->AssignWindow("button_prefs",btnPrefs); wxSkinEngine::Get()->AssignWindow("mute",chkMute); //initialize the skin wxSkinEngine::Get()->InitializeSkin(); //add the wxMediaCtrl in a sizer that will be handled "special" when added to a skinned frame wxBoxSizer* b = new wxBoxSizer(wxVERTICAL); b->Add(media,1,wxEXPAND,0); frame->SetSizer(b); frame->Show();
Code: Select all
wxSkinEngine::Get()->ClearSkin(); wxSkinEngine::Get()->Load(skinfile,true); wxSkinEngine::Get()->InitializeSkin();
I'll work some more on this and maybe create an example showing a "real", meaning complex, frame. But for now I guess this is enough eye-candy
I hope you like it and think that it is a good idea. Comments and suggestions are welcome, flaming and emails like "gimme da source" are not. I will release wxSkin once I'm done or decide to make it public. Right now I want some more time to develop it further.