wxRichTextCtrl не фонтан

January 12th, 2008 Begemot

Как я и боялся wxRichTextCtrl не всегда адекватен. За час тестов я нашел кучу “странного поведения”, и раза 4 он херил мне стиль всего документа. В результате несложных манипуляций- то весь текст стает жирным, то центрированным, самый тяжелый случай – при ресайзе окна весь текст превратился в сплошной список, каждый пункт которого начинался с ‘1’ и всеб было bold & italik. Ну и как я могу дать подобное юзерам? Ответил Julian Smart’y на его предложение юзать wxRichTextCtrl, описанием багов и методикой воспроизведения одной из ситуаций, посмотрим что ответит – как никак он автор.

Уточню, речь шла о использовании wxRichTextCtrl  как РТФ редактора. Мысль о том, что можно попробывать эмулировать им простой эдит с расширенной функциональностью все еще не покидает меня – буду пробывать.

Posted in Oбщее | Tags: , ,
Comments Off on wxRichTextCtrl не фонтан


Мягкая часть тела с Edit’ами

January 10th, 2008 Begemot

Просто какая-то отвратительная ситуация с эдитами в мире, причем не  в wxWidgets а в целом. Не могу подобрать идеальный Edit Control для своей задачи, хотя требования у меня довольно простые, без особых наворотов.

Чего хочется:

  1. Функциональность обычного простого эдита (notepad)
  2. _Обязательно_ множественное undo\redo.
  3. _Желательно_ подсветка и клик на ссылках.
  4. Корректная работа с точки зрения пользователя.
  5. Хотелось бы иметь возможность в будущем (опционально) перейти на RTF если стукнет в голову.

Собственно если говорить про MSW и wxWidgets, есть 4 варианта:

  1. Обычный edit control (CEdit, wxTextCtrl, Notepad) – (2) обязательное условие не выполняется.
  2. RTF контрол (CRichTextCtrl, wxTextCtrl+wxTE_RICH, WordPad) – все пункты кроме (4) выполняются. На скорость работы и совместимость версией под линукс можно забить пока, но (4) условие не выполняется. Для пользователя контрол должен выглядеть простым (не ртф) – соответвенно вставять и копировать _только_ plain text, этого добиться не получается.
  3. wxWidgets версию RTF контрола wxRichTextCtrl (generic, ground-up implementation of a text control capable of showing multiple styles and images.) – Как-то она вообще не внушает доверия в плане работы, к тому же пункт (5) вызывает определенные проблемы.
  4. Scintilla – там что-то непонятное с RTF, с одной стороны он умеет с ним работать – сохранять файлы как RTF, копировать в буфер – но полноценной работы я не нашел.

Наверное забью я в итоге на пользователей (и на себя самого, потому что от отсутствия ундо я сам страдаю) и возьму для начала обычный edit.


Человеческая реализация Find&Replace для wxTextCtrl

December 25th, 2007 Begemot

Мда _человеческая_ реализация Find&Replace для wxTextCtrl требует мозгов, почти рабочий день и кучу тестирования. Интересно почему не добавят такую возможность к стандартному контролу?

Posted in Uncategorized | Tags:
Comments Off on Человеческая реализация Find&Replace для wxTextCtrl


Реализуем поиск в wxTextCtrl

December 24th, 2007 Begemot

Потребовалось мне значит добавить стандартные процедуры -  find, find next, replace. wxTextCtrl напрямую их не поддерживает, так что приходится писать руками. Полез искать примеры – самому писать немного муторно – надо много чего учитывать, а велосипед изобретать не хотелось – задача то по идее тривиальная. Как оказалось легче все таки самому:) Все велосипеды, что нашлись были или сильно самописыными (без использования стандартных диалогов) или вообще кривыми самокатами. Наиболее подходящим оказался вот этот код, сразу видно писал крутой программист и ему было не до тестрования.

И еще не могу понять почему все пытаются использовать Get\SetInsertionPoint когда помоему правильнее юзать только Get\SetSelection?

void FlashnoteFrame::OnFind()
{
     wxString find = m_findData.GetFindString();
    int flags = m_findData.GetFlags();
   

    bool forward(flags & wxFR_DOWN);
    long m_foundPos, StartFromBack, StartFromForward;
    m_Note->GetSelection(&StartFromBack, &StartFromForward);

    wxString string = forward ? m_Note->GetRange(StartFromForward, m_Note->GetLastPosition()) : m_Note->GetRange(0, StartFromBack);

    if (flags & wxFR_MATCHCASE)
            m_foundPos = forward ? string.find(find) : string.rfind(find);
    else
           m_foundPos = forward ? string.Lower().find(find.Lower()) : string.Lower().rfind(find.Lower());

    if (m_foundPos==-1) return;

    long startPos = forward ? StartFromForward + m_foundPos : m_foundPos;
    long endPos = startPos + find.length();

    m_Note->SetSelection(startPos, endPos);
}

Posted in Программирование
Comments Off on Реализуем поиск в wxTextCtrl


Копайте и выкопаете

December 23rd, 2007 Begemot

Я уже писал про проблему навигации по дереву из другого контрола. Все таки я ее решил.

Задача – в окне есть дерево и другие контролы (у меня только редактор, но думаю что решение масшабируется),  необходимо дать юзеру возможность перемешаться по ветвям дерева не заставляя его сначала переключить туда фокус а потом вернутся назад.

Решение  – для навигации используется 6 клавиш (стрелки и Page Down\UP), для навигации из другого контрола используем АЛТ+соответствующая клавиша. Отслеживаем все нажатия клавиш и редиректим нужные нашему дереву.

Код:

Сразу предупреждаю что решение только для Винды. Как сделать для Макоса и Юникса еще не знаю, но очень хочу:)

1. В наше дерево добавляем метод

#ifdef __WIN32__

void

CMyFNTreeCtrl::EmulateKeyPress(const wxUint32 keycode)

{

    wxWindow * OldFocus=FindFocus();

    SetFocus();

     keybd_event((BYTE)keycode, 0, 0

/* key press */, 0);

     keybd_event((BYTE)keycode, 0, KEYEVENTF_KEYUP, 0);

      wxYield();

     OldFocus->SetFocus();

}

#endif // __WIN32__

Поскольку я все равно сабкласю дерево – то я добавил метод в него , но разумеется это можно сделать и прям в основном коде или просто процедурой – как угодно, главное код.

 

2. У меня есть процедура которая обрабатывает все нажатия на форме и в дочерних контролах. В ней пишем:

 

void FlashnoteFrame::OnChar( wxKeyEvent& event )
{
    wxChar key=event.GetKeyCode();
    wxObject * object=event.GetEventObject();

    if (event.GetModifiers() == wxMOD_ALT )
    {
        switch(key)
        {   
#ifdef __WIN32__ // Navigation through tree from any place with ALT
            case WXK_RIGHT:            
            case WXK_LEFT:
            case WXK_UP:
            case WXK_DOWN:
            case WXK_PAGEDOWN:
            case WXK_PAGEUP:
                if (object!=m_Tree)
                {
                    m_Tree->EmulateKeyPress(event);
                    return;
                }
#endif // __WIN32__
            default: ;
        }
    }
    event.Skip();
}

3. Все работает, но есть одна проблема.  В эдите зажимаем АЛТ, перемещаемся на нужную ветвь дерева, бросам АЛТ – пытаемся писать в эдите, нажимаем первую буквенную клавишу – получаем фигню (либо ничего, либо псевдографику, либо еще что-то). Проблема была у меня и под MFC. решается так

 

#ifdef __WIN32__
void CMyFNTextCtrl::OnKeyUp( wxKeyEvent& event )
{
    // Съдаем отпускание альта, иначе после навигации по дереву из редактора с альтом, первое нажатие буквенно цифровой клавиши
    // глючит или артефакт (квадратик) или другая буква или вообще ничего не происходит
    if (event.GetModifiers() == wxMOD_ALT ) return;

    event.Skip();       
}
#endif // __WIN32__

Разумеется это обработчик события отпускания клавиши для эдита.

Posted in Программирование
Comments Off on Копайте и выкопаете


wxLaunchDefaultBrowser and FireFox

December 22nd, 2007 Begemot

Обнаружил что wxLaunchDefaultBrowser работает криво. У меня FF стоит по умолчанию, если броузер уже запущен руками – то wxLaunchDefaultBrowser работает нормально. Но если FF закрыт, то облом – запускает фаерфокс, открывает новую вкладку – но пустую. Второй выбор этого же пунта меню для перехода на домашнюю страницу – опять открывает пустую вкладку и так пока не закроешь все вкладки и не откроешь броузер руками. Причем если в такую “открытую” вкладку руками вбить адрес – все равно ФФ не работает. жопа. Если дождусь письмо от sourceforge.net для активации аккаунта – запощю баг в трекер.

Updated: Как всегда если вам кажется что компьютер или система глючит – проверяйте себя. Оказалось проблема в моей системе – Firewall блокировал, дебаг версию – в результате чего был такой баг.

Posted in Oбщее
Comments Off on wxLaunchDefaultBrowser and FireFox


Сохранение Layout’a

December 21st, 2007 Begemot

Научился нормально сохранять размеры\положение окна, тоже вам скажу не тривиальная задачка, хотя может я тормоз – но целый день с ней провозился, надо наверное запостить на днях алгоритм сюда. Но сейчас речь о другом – хочется еще и внутренний лайот сохранять. Использую AUI, лайот простой вот тут скриншотик можно глянуть. Вообщем варианта целых два : либо храним весь лайот в виде строки в файле использую AUI Save\LoadLauoyut или делаем все ручками – благо мне для этого дизайна всего 3 параметра надо хранить. Оба способа не фонтан.

Второй, в принципе хорош для данного приложение – но особо не масштабируется, а это софтина просто тренировка\проверка wx перед более сложной.

Первый – хорош с точки зрения простоты реализации, но плох для пользователя. Дело в том, что если я в следующей версии меняю лайот – добавляю например новую панель – сохраненый юзать нельзя. Но и это еще не все – даже если я просто поменяю мелкий аспект в поведении панели, например разрешу ей плавать или показывать кнопку закрытия в загловке панели со следующей версии – сохраненый лайот придется сносить. Также подозреваю возможные проблемы с локализацией (!). Вообщем технически легко, но как пользователи посмотрят на то что их настройки постоянно сбрасываются? Вам бы понравилось если бы к примеру Visual Studio раз в месяц обновлялась и сносила все ваши настройки?:)

Вообщем думаю что выбрать, может комбинированный способ.

Posted in Программирование
Comments Off on Сохранение Layout’a


Shit happens

December 21st, 2007 Begemot

Эхх, клонирую свою MFC программу под wxWidgets. Необходимо находясь в эдит контроле иметь возможность навигации по соседнему дереву, там я  просто просто в PreTranslateMessage в эдите отлавливал alt+стрелки\Page Down\UP менял обьект у события и форвадил дереву для обработки. На wx сделать не получалось, спросил в wx-users at lists.wxwidgets.org, в ответ от Vadim Zeitlin  получил

There is no way to make this work with native controls (such as wxTreeCtrl
under MSW): they have no idea about wx events so sending them to those
controls will obviously never do anything. We thought a few times in the
past to provide a way to generate a native keyboard message from e.g.
wxKeyEvent but this has never been done. If you feel like trying to do it,
it would certainly be welcome. Otherwise you will have to handle the keys
yourself manually (i.e. checks for arrow up and select the appropriate item
and so on).

Настроение с утра испортил:)

Иногда я думаю что лучше бы я писал какие-нибудь сложные алгоритмы, вместо написания простых софтин и постоянного траханья с интерфейсом и юзабилити.

Будем копать дальше, гда наша не пропадала:)

Posted in Oбщее | Tags: ,
Comments Off on Shit happens


wxWindowDestroyEvent

December 20th, 2007 Begemot

В обработчике wxWindowDestroyEvent окно уже какое-то полудохлое, такое ощушение что еще не совсем умерло, но уже попахивает. При IsMaximized() получаем AV. Так что MFCшники бросайте привычку делать что-то в OnDestroy, дружно юзаем деструктор.

Posted in Oбщее | Tags: ,
Comments Off on wxWindowDestroyEvent


wxWindowCreateEvent много раз

December 19th, 2007 Begemot

This event is sent just after the actual window associated with a wxWindow object has been created. Since it is derived from wxCommandEvent, the event propagates up the window hierarchy.

Обратите внимание на выделенное. Если хотите использовать этот событие для дополнительной инициализации диалога, по аналогии с OnInitDialog в MFC, то учтите: обработчик OnCreate для wxWindowCreateEvent вызывается много раз, первый раз после инициализации фрейма, а потом после создания каждого контрола. Так что или выберите другое место для дополнительной инициализации или предохраняйтесь:

if(event.GetEventObject()==this)

{

….

}

Posted in Oбщее | Tags: ,
Comments Off on wxWindowCreateEvent много раз