segunda-feira, 16 de julho de 2007

Cá se fazem, cá se pagam

Não vivo em Lisboa e as eleições intercalares para a Câmara Municipal pouco talvez nada me despertaram o interesse. Sempre vou pensando que, sendo um local onde milhares de pessoas passam a maior parte do tempo útil, muitos mais deviam ser consultados; outras contas do rosário...

Mas (mesquinho, mesquinho) o resultado do Paulo Portas é o meu destaque. Depois da canalhice que ele fez ao Ribeiro e Castro, com aquela soberba de "vou-me embora e volto quando quero", tudo o que politicamente negativo lhe acontecer é merecido. E só fico satisfeito quando for derrotado internamente.

Etiquetas:

wxGenericDirCtrl events

I got stumped when trying to catch the file selected with the generic directory tree: there are no events in that control! After some googling I understood: the "selection" event is fired by the tree control, not by the window / control that contains it; if ID_DIR_CTRL is the generic control ID this does not work:
BEGIN_EVENT_TABLE(MyFrame,wxFrame)
EVT_TREE_SEL_CHANGED(ID_DIR_CTRL, MyFrame::OnTreeSelChanged)
END_EVENT_TABLE()

One solid solution was pointed by Joseph Blough using a dynamic connection, that is an (more object like) alternative to event tables. I'll check that on a sunnyless Sunday, for now I stick with the old event table setting the wxTreeCtrl ID:
dirCtrl->GetTreeCtrl()->SetId(ID_TREE_CTRL);
Documentation says that the identifier should not be modified but, hey, I'm setting it in the constructor. And it works!


Update terça-feira, 17 de Julho de 2007:

No, it does not work. Events are catched, but are also lost by the generic directory tree. Sunnyles Sunday on Tuesday, that is. I could get all tree events with wxID_ANY but I'm seeing some more trees coming...

Etiquetas:

domingo, 15 de julho de 2007

Sliding separator news

First version of the sliding separator has a major flaw: if the windows are inside a sizer, item's proportion must be changed at motion or mouse up (I think mouse up is enough). For that wxWindow:­:GetContainingSizer, wxSizer:­:GetItem and wxSizerItem:­:SetProportion may be used. Other windows in the sizer can't be disturbed, so the sum of the two proportions must be constant. There is a list of problems to solve:

- both windows should be proportional, or not: resizing a proportional window with a not proportional window is likely to afect other items.
- a proportional window with minimum size can't get proportion = 0.
- windows with size = 0 and proportion = 0 must be accepted as proportional, in case a window is completely hidden using the slider.

Now the problem is that on mouse up I don't know if the window has proportion = 0 because it was hidden or because it is not proportional, so I have to check on mouse down if the slide can be done and capture the mouse only when all is ok:
void SlideSep::OnLeftDown(wxMouseEvent& event) {
wxSizer* sz = m_windowTL->GetContainingSizer();
if (sz != m_windowBR->GetContainingSizer()) {
wxLogDebug(_T("Adjacent windows should have the same sizer!"));
event.Skip();
return;
}
if (sz) {
wxSizerItem* i1 = sz->GetItem(m_windowTL);
wxSizerItem* i2 = sz->GetItem(m_windowBR);
wxSize s1 = m_windowTL->GetSize();
wxSize s2 = m_windowBR->GetSize();
int p1 = i1->GetProportion();
int p2 = i2->GetProportion();
if ( (p1 || !s1.x) != (p2 || !s2.x) ) {
wxLogDebug(_T("Both items should be proportional, or not!"));
event.Skip();
return;
}
}
m_startPoint = event.GetPosition();
this->CaptureMouse();
event.Skip();
}

Mouse motion has no changes, all proportional stuff is done in mouse up. If capture is lost same changes apply:
void SlideSep::OnLeftUp(wxMouseEvent& event) {
if (HasCapture()) {
this->ReleaseMouse();
OnReleaseMouse();
}
event.Skip();
}

void SlideSep::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) {
OnReleaseMouse();
}

When the mouse is released proportions are changed. If proportions are small numbers a Layout is needed to fix: if I have three windows with proportions 2,5,3 then each window has to be a multiple of 1/10 of the space available; to have a "continuous sliding" proportions must be big numbers like 2000,etc.
void SlideSep::OnReleaseMouse() {
wxSizer* sz = m_windowTL->GetContainingSizer();
if (sz && sz == m_windowBR->GetContainingSizer()) {
wxSizerItem* i1 = sz->GetItem(m_windowTL);
wxSizerItem* i2 = sz->GetItem(m_windowBR);
int p1 = i1->GetProportion();
int p2 = i2->GetProportion();
if (p1 || p2) {
wxSize m1 = m_windowTL->GetMinSize();
wxSize m2 = m_windowBR->GetMinSize();
wxSize s1 = m_windowTL->GetSize();
wxSize s2 = m_windowBR->GetSize();
int ss = s1.x + s2.x;
int pp = p1 + p2;
p1 = (int)((double)pp * s1.x / ss + 0.5);
if (p1 == pp && m2.x != 0) p1--;
if (p1 == 0 && m1.x != 0) p1++;
p2 = pp - p1;
i1->SetProportion(p1);
i2->SetProportion(p2);
sz->Layout();
}
}
}


Source files are here. I'm going back to main project now.

Etiquetas: ,

sábado, 14 de julho de 2007

Flash games

Nos últimos tempos tenho visitado frequentemente o sítio do Graeme, lazylaces, que tem quase sempre uns joguitos flash novos. A maior parte são do tipo "aponta e clica" e seriam irritantes se não fossem os comentários que ajudam a acabar os jogos sem revelar tudo.

Existem excepções, como o Detective Grimoire. Fácil de terminar sem ajuda, apesar de não ter percebido completamente como os suspeitos passam a inocentes; mas próximo do fim qualquer pessoa já percebeu quem é o culpado. Além disso tem um "making of" interessante para quem conhece o Flash.

E existem pérolas como esta:

Etiquetas:

quinta-feira, 12 de julho de 2007

The SlidingSeparator

Yep, reusable objects are always fun. The problem with wxSplitter­Window is that it is intended to split a window / document, not to separate two windows / objects. The alternative is the sash window but this doesn't have a live update, and only exposes the dragged event. Ah, who am I fooling with all these excuses? I want to make a sliding separator, that's all!

With live update it's easy. You put a tiny window between the other two, catch the mouse down event, store current mouse position and capture the mouse. On motion the tiny window follows the mouse and the neighbours are sized / positioned according. On mouse up the fellow is released from the capture. With no live update -- that is, with a "shadow separator" -- things aren't so straight, you have to draw on the screen.

Now the details: you can't move the handle outside his area, and should keep an eye on the mouse capture. WxWidgets has a wxWindow:­:GetMinSize, that must be respected and solves the first problem. The wxMouse­CaptureLost­Event solves the second; this event is currently emitted under Windows only, with Linux you can't Alt-Tab while the mouse is captured, afaics.

Digesting:
SlideSep::SlideSep(wxWindow* parent, wxWindow* top_left, 
wxWindow* bottom_right, wxWindowID id,
const wxPoint& pos, const wxSize& size)
: wxWindow(parent, id, pos, size) {

SetCursor(wxCursor(wxCURSOR_SIZEWE));
m_windowBR = bottom_right;
m_windowTL = top_left;
}

void SlideSep::OnLeftDown(wxMouseEvent& event) {
this->CaptureMouse();
m_startPoint = event.GetPosition();
event.Skip();
}

void SlideSep::OnMotion(wxMouseEvent& event) {
if (HasCapture()) {
// TODO: implement orient
int dx = event.GetPosition().x - m_startPoint.x;
wxSize m1 = m_windowTL->GetMinSize();
wxSize m2 = m_windowBR->GetMinSize();
wxSize s1 = m_windowTL->GetSize();
wxSize s2 = m_windowBR->GetSize();
// space available is size - minSize
int av1 = m1.x == -1? s1.x: s1.x - m1.x;
int av2 = m2.x == -1? s2.x: s2.x - m2.x;
// limit move to space available
if (-dx > av1) dx = -av1;
if (dx > av2) dx = av2;
if (dx != 0) {
m_windowTL->SetSize(s1.x +dx, s1.y);
wxPoint p = this->GetPosition();
this->Move(p.x +dx, p.y);
p = m_windowBR->GetPosition();
m_windowBR->SetSize(p.x +dx, p.y, s2.x -dx, s2.y);
}
}
event.Skip();
}

void SlideSep::OnLeftUp(wxMouseEvent& event) {
if (HasCapture()) {
this->ReleaseMouse();
}
event.Skip();
}

void SlideSep::OnCaptureLost(wxMouseCaptureLostEvent& WXUNUSED(event)) {
// in Windows there is a debug alert without this
}


As reference the complete source files are here. It works well with no sizer, but there is no point about that. As expected, with a box sizer item's proportion rules when the window is resized -- next problem to be solved.

For now I'm loosing the native sash look, but maybe the DrawSplitterSash method is what I need.

Etiquetas: ,

terça-feira, 10 de julho de 2007

wxWidgets prototype done

Making the window was easy until the sliding separator part. The best source to learn what objects are available is the "Classes by category" list, the alphabetical list is too messy to start.

The menu is a wxMenu object and the tool bar is a frame managed toolbar. What I call properties is a wxNotebook control and the tree list can be a standard tree control or a wxWidgets custom control with all directories. Having all dirs is not as I thought at first, and I see no way to override the filter, but to start the wxGenericDirCtrl is what I need.

I am still fighting with the best approach [?] to the sliding separator, the wxSplitterWindow. It is intended to show two views of the same document and the behaviour is not always as I want:
- it looses the handler when I drag it to the limits, the split action is to be done by other control like the menu; with minimum pane size = 1 the handler is always visible but that pixel is ugly.
- resizing is... ahuum... strange; I had to catch the handler [sash] position changed event and compute the sash gravity to get something near what I want; tests made with the box sizer show that can be better.

The splitter window is right to a prototype but I have to change that soon. Making reusable objects is always fun, and I'm thinking about a SlidingSeparator as I see it.

Etiquetas: ,

segunda-feira, 9 de julho de 2007

My wxWidgets learning project

I usually make a "not-so-minimal" project for every tool I evaluate. To keep focus it must have some realistic goal; right now I have one project with some key characteristics:

- read binary files, to evaluate the little-endian / big-endian solution and Linux utf-8 / Windows ucs-16 compatibility. With some platforms the bytes must be swapped after reading binary integers, with others there is no need (with Macs using Intel processors most desktop computers are now little-endian).

- use some "high-level control", like the tree or list controls, to evaluate the trust one may have to develop continually in one platform, minimizing the inevitable platform switch. Here I should use VMware Virtual Machines or run inside coLinux, but I doubt my hardware allows it. I will test one solution like that as a proof of concept, but a multi-platform development environment needs to run the platforms side by side; one easy solution is a computer for each platform.

- use sizers; well, any project would use it anyway.


Once I need a program to check fonts for unicode code points availability, like the infamous surrogated code points. Default font viewers are not very informative and the best program I found was Steve Hartwell's Font Inspector, a wxWidgets project by the way; the program had a date limit and Steve Hartwell's home page is no longer available, so my wxWidgets learning project is something around that - not the visual inspector that Steve's program was, maybe a little of that, but a tool that can filter fonts by unicode named range support and check for the existence of any code point.

Not very usefull, that's all right. Just a goal to keep me on the road.

Etiquetas: ,

Preparing wxWidgets workspace

After a good "first sight" impression about wxWidgets I decide to take a "deep look" into the product. With some hardware issues in the middle it took me about one week to get stable Linux distros running, but the integration of Windows and Linux development was easy. Windows was already set up so I used a Linux-only package [GTK] to build, with a structure analogous to Windows with debug and release under build/gtk (with sudo as needed):
mkdir /devel
cd /devel
tar -xof /download path/wxGTK-x.x.x.tar.gz
cd wxGTK-x.x.x/build
mkdir gtk
cd gtk
mkdir debug
cd debug
../../../configure --with-gtk --enable-debug
make (play some games)
cd ..
mkdir release
cd release
../../../configure --with-gtk [ --disable-shared ?]
make (to do, need to learn about the shared option)

Default configuration creates make files for wxWidgets samples. To make the "minimal sample" debug version:
cd /devel/wxGTK-x.x.x/build/gtk/debug/samples/minimal
make

Errors found [u] is Ubuntu, [p] is PCLinuxOS

C compiler cannot create executables [u]
Install build-essential package with Synaptic or apt-get

some error about compiler [p]
Install gcc-c++ package

The development files for GTK+ were not found [u] [p]
Install standard C and GTK libraries:
libstdc++6-devel, libgtk+2.0-0-devel [p]
libstdc++6-4.1-dev, libgtk2.0-dev [u]

other errors when making wxWidgets [u] [p]
After messing around with configurations and invalid makes you may need to "make clean" before "make" again

cannot find -lwx_gtk2d_core-x.x when making a sample [u] [p]
Did you make wxWidgets after configure?


Workspace options

Source share between Windows and Linux may not be an out of the box option: some Linux distros dont have NTFS write, and Windows dont have Ext3 access. On the Linux side install ntfs-3g, in STABLE status since February 2007 after twelve years of development; on the Windows side install Ext2 File System For Windows, it deals well with ext3 without journal imple­mentation (just as older Linux Kernels which do not know the Ext3 file system).

I've made exe files in the Ext3 partition (running Windows) and bin files in the NTFS partition (running Linux) without problems. The trick part was to pull the projects from wxWidgets folders, with all these includes and flags the safest way is to copy the project files and change paths with a text editor.

This is my workspace scheme:
project (folder)
common sources (h, cpp)
gtk (folder)
platform sources (xpm)
debug (folder)
Makefile
release (folder)
Makefile
msw (folder)
platform sources, project (ico, rc, dsw, dsp)
vc_mswud (make folder)
vc_mswu (make folder)

The "minimal" project can be transposed outside wx folders with Makefile copies from build/gtk/xxx/samples/minimal for Linux, and .dsw;.dsp copies from samples/minimal for Windows MSVS. Makefile and .dsw;.dsp need path changes, just a replacement for the first and find/replace for the last. There is a catch, however: resources are taken from the samples folder (minimal.rc is not used) and that needs special care.

On the Windows side I've make a share of the wxWidgets folder and use \\host\share as wx dir, this gives me greater flexibility. After tests with multiple configurations, in Windows and Linux, I've clean and compact the extracted "minimal" project as a start for wxWidgets projects. It is highly portable, I used it with two Windows installations with different drive letters and two Linux distros, in NTFS and Ext3, without changes. Now its time for my wxWidgets learning project.

Etiquetas:

sexta-feira, 6 de julho de 2007

Ubuntu vs PCLinuxOS

Depois dos problemas que tive devido aos sectores danificados do meu disco de arranque [?] consegui instalar o Ubuntu. Esperando algum tempo [para ultrapassar a verificação de erros?], talvez depois de ter montando os dispositivos a pedido, sei lá, finalmente o Ubuntu conseguiu mostrar a partição que eu tinha preparado e fazer a instalação.

Gastei o tempo livre dos dias seguintes a melhorar a escolha do sistema operativo (boot loader) e a comparar o Ubuntu com o PCLinuxOS. Apesar da má impressão inicial escolhi o primeiro.

O ambiente de trabalho do PCLinuxOS é demasiado parecido com o Windows, até tem um botão tipo "Start" pré-XP e um ícone "My computer". E os temas de arranque foram obviamente feitos por engenheiros como eu, sem jeito nenhum para o lado estético. Como positivo, os painéis de controlo estão funcionais e visivelmente agradáveis.

O Ubuntu é um projecto mais maduro. O sistema e muitas, muitas aplicações, têm versão em Português. A escolha de aplicações e utilitários é baseada na popularidade e apenas as presumivelmente melhores são instaladas, mas existe um largo repositório de programas com instalação fácil. O carácter universal do Ubuntu é realçado pelo tema assumido, com um sabor nitidamente africano; clica na imagem para ouvir o som de arranque.

Etiquetas: