quarta-feira, fevereiro 07, 2007

Curso de wxWidgets, post 13: Formatando texto

Para finalizar o editor de textos, vamos adicionar formatação a ele. Para isto, irei usar uma função que já vimos no curso: wxGetFontFromUser().

Primeiro, vamos incluir o cabeçalho da função:

#include <wx/fontdlg.h>


Vamos também criar um novo método para a formatação. Este método irá se chamar MeuFrame::Formatar(). Vamos declarar a nova função na definição da classe:


class MeuFrame: public wxFrame
{
...
private:
...
void Formatar(void);
}


E agora, implementemos o método:


// Formatação
void MeuFrame::Formatar(void)
{
long inicio, fim;
wxTextAttr attr;
wxFont font;

// Obtém a formatação atual (não suportado em todas as plataformas)
txt_file->GetSelection(&inicio, &fim);
txt_file->GetStyle(inicio, attr);
font = attr.GetFont();

// Altera a formatação
font = wxGetFontFromUser(this, font);
attr.SetFont(font);
txt_file->SetStyle(inicio, fim, attr); // Aplica o estilo ao texto
}


Primeiro, o método tenta obter a formatação atual do texto selecionado (wxTextCtrl::GetStyle() não é suportado em todas as plataformas, testei no Linux e não funcionou). Após obter a formatação, iremos utilizá-la em wxGetFontFromUser() para inicializar os valores da janela, assim, sempre a janela de formatação for aberta, ela estará configurada com a formatação atual.

Em seguida, wxGetFontFromUser() retorna a nova formatação e podemos aplicá-la ao texto selecionado.

Agora devemos criar um botão na barra de ferramentas para este método. Vamos adicionar uma ID para este botão:


// IDs
enum
{
ID_TBAR_NEW,
ID_TBAR_LOAD,
ID_TBAR_SAVE,
ID_TBAR_FORMAT, // Este foi adicionado
ID_TBAR_ABOUT
};


E criamos o novo botão no construtor de MeuFrame:


tbar->AddTool(ID_TBAR_FORMAT, wxString(wxT("Formatar")), \
wxBitmap(wxT("/usr/share/pixmaps/gedit-icon.png"), wxBITMAP_TYPE_PNG));


Pronto! Está feito. :)



Próximo passo

O editor de textos pára por aqui. Estou querendo falar sobre sockets no próximo post, mas precisarei elaborar um texto maior, pois tem bastante coisa pra explicar. Se alguém quiser aprender algo específico do wxWidgets, postem nos comentários. Assim vocês me ajudam a escolher o próximo assunto. :)

Como sempre faço, o código-fonte completo está abaixo:

/* A Casa de Just - http://jpjust.blogspot.com
* Curso de wxWidgets: Um editor de textos
*
* O objetivo deste código-fonte é demonstrar diversas classes
* ensinadas no curso de wxWidgets do blog "A Casa de Just".
*
* As aulas do curso de wxWidgets podem ser encontradas em forma
* de posts no blog: http://jpjust.blogspot.com
*
* Copyright (c) João Paulo Just <jpjust@justsoft.com.br>
* A Casa de Just - http://jpjust.blogspot.com
* 07 de fevereiro de 2007, 20:24, Ilhéus, BA, Brasil.
*/

#include <wx/wx.h>
#include <wx/fontdlg.h>

// IDs
enum
{
ID_TBAR_NEW,
ID_TBAR_LOAD,
ID_TBAR_SAVE,
ID_TBAR_FORMAT,
ID_TBAR_ABOUT
};

// Classe do programa
class MeuPrograma: public wxApp
{
public:
// Método principal
virtual bool OnInit(void);
};

// Classe do frame
class MeuFrame: public wxFrame
{
public:
// Construtor
MeuFrame(void);

// Eventos
void OnToolBarClick(wxCommandEvent &event);

// Métodos auxiliares
void Novo(void);
void Abrir(void);
void Salvar(void);
void Formatar(void);
void Sobre(void);

DECLARE_EVENT_TABLE()

private:
// Widgets do frame
wxTextCtrl *txt_file;
wxToolBar *tbar;
wxStatusBar *stbar;
};

// Inicialização do programa
bool MeuPrograma::OnInit(void)
{
wxInitAllImageHandlers(); // Inicia todos os hadlers de imagens do wxBitmap

MeuFrame *frame = new MeuFrame();
frame->Show();
SetTopWindow(frame);
return true;
}

// Tabela de eventos
BEGIN_EVENT_TABLE(MeuFrame, wxFrame)
EVT_TOOL_RANGE(ID_TBAR_NEW, ID_TBAR_ABOUT, MeuFrame::OnToolBarClick)
END_EVENT_TABLE()

// Construtor do frame
MeuFrame::MeuFrame(void)
:wxFrame(NULL, wxID_ANY, wxT("Editor de textos - http://jpjust.blogspot.com"))
{
// Sizer e widgets
wxBoxSizer *sizer_v = new wxBoxSizer(wxVERTICAL);

txt_file = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);

// Barra de ferramentas
tbar = new wxToolBar(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTB_TEXT);

tbar->AddTool(ID_TBAR_NEW, wxString(wxT("Novo")), \
wxBitmap(wxT("/usr/share/pixmaps/gedit-icon.png"), wxBITMAP_TYPE_PNG));

tbar->AddTool(ID_TBAR_LOAD, wxString(wxT("Abrir")), \
wxBitmap(wxT("/usr/share/pixmaps/gnome-folder.png"), wxBITMAP_TYPE_PNG));

tbar->AddTool(ID_TBAR_SAVE, wxString(wxT("Salvar")), \
wxBitmap(wxT("/usr/share/pixmaps/gnome-cd.png"), wxBITMAP_TYPE_PNG));

tbar->AddSeparator();

tbar->AddTool(ID_TBAR_FORMAT, wxString(wxT("Formatar")), \
wxBitmap(wxT("/usr/share/pixmaps/gedit-icon.png"), wxBITMAP_TYPE_PNG));

tbar->AddSeparator();

tbar->AddTool(ID_TBAR_ABOUT, wxString(wxT("Sobre")), \
wxBitmap(wxT("/usr/share/pixmaps/gnome-info.png"), wxBITMAP_TYPE_PNG));

tbar->Realize();

// Barra de status
stbar = new wxStatusBar(this);
stbar->SetStatusText(wxT("Sem título"));

// Posicionamento
sizer_v->Add(txt_file, 1, wxALL | wxEXPAND, 5);

SetSizerAndFit(sizer_v);

// Insere a barra de ferramentas e a barra de status
SetToolBar(tbar);
SetStatusBar(stbar);
}

// Limpa a tela para um novo arquivo
void MeuFrame::Novo(void)
{
int msg = wxMessageBox(wxT("Deseja salvar o arquivo atual antes de criar um novo?"), \
wxT("Novo arquivo"), wxYES_NO | wxCANCEL);

if (msg == wxYES) // Salva
Salvar();
else if (msg == wxCANCEL) // Cancela a operação
return;

// Cria um novo arquivo
txt_file->Clear();
stbar->SetStatusText(wxT("Sem título"));
}

// Abre um arquivo
void MeuFrame::Abrir(void)
{
wxString Filename;

// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxOPEN | wxFILE_MUST_EXIST);

// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;

txt_file->LoadFile(Filename);

// Atualiza o nome
stbar->SetStatusText(Filename);
}

// Salva o arquivo aberto
void MeuFrame::Salvar(void)
{
wxString Filename;

// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxSAVE | wxOVERWRITE_PROMPT);

// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;

txt_file->SaveFile(Filename);

// Atualiza o nome do arquivo
stbar->SetStatusText(Filename);
}

// Formatação
void MeuFrame::Formatar(void)
{
long inicio, fim;
wxTextAttr attr;
wxFont font;

// Obtém a formatação atual (não suportado em todas as plataformas)
txt_file->GetSelection(&inicio, &fim);
txt_file->GetStyle(inicio, attr);
font = attr.GetFont();

// Altera a formatação
font = wxGetFontFromUser(this, font);
attr.SetFont(font);
txt_file->SetStyle(inicio, fim, attr); // Aplica o estilo ao texto
}

// Janela "Sobre"
void MeuFrame::Sobre(void)
{
wxMessageBox(wxT("Curso de wxWidgets\n\nhttp://jpjust.blogspot.com"), wxT("Sobre"), wxICON_INFORMATION);
}

// Método para a barra de ferramentas
void MeuFrame::OnToolBarClick(wxCommandEvent &event)
{
switch (event.GetId())
{
case ID_TBAR_NEW:
Novo();
break;

case ID_TBAR_LOAD:
Abrir();
break;

case ID_TBAR_SAVE:
Salvar();
break;

case ID_TBAR_FORMAT:
Format();
break;
}
}

IMPLEMENT_APP(MeuPrograma)