psilogic: (Default)
psilogic ([personal profile] psilogic) wrote2008-12-06 01:33 pm

Небольшая авантюра :)

И до чего же мне остопи... осточертели разнообразные глюки виндового контрола ListView. В один прекрасный день я осознал, что на периодический отлов и исправление подобных глюков было потрачено много дней. Ну и решился я на такую авантюру: написать этот класс "ручками", так сказать, под себя. Пока получается. Позавчера сделал отображение и скроллинг, вчера - множественный выбор и перетаскивание/растягивание заголовков. Как там говорится в одной программистской поговорке: никогда не находится время, чтобы сделать что-то необходимое, но всегда находится время, чтобы переделать ;)



Это, кстати, к вопросу, как дела с bard-ом. Нормально дела, вовсю идет работа над новой версией.

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 05:30 pm (UTC)(link)
ты знаешь что-то лучше сигналослотов? для цпп, натурально.

[identity profile] psilogic.livejournal.com 2008-12-09 05:31 pm (UTC)(link)
виртуальные функции классов :)

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 05:39 pm (UTC)(link)
ну-ну. и с ними совсем-совсем без гемора делаются связи "многие ко многим", например? и я в рантайме могу переназначать реакции? это какое-то очень сильное колдунство, это компилятор c++ и исходники надо в рантайме иметь. и технологию патчинга рабочего кода. ты считаешь, это менее черезжопно? %-)

[identity profile] psilogic.livejournal.com 2008-12-09 05:53 pm (UTC)(link)
у меня обработка событий идет так. изначально событие получает некий контрол (обычно тот, который сам его породил). потом событие передается вверх по иерархии layout-ов до родительского окна. на каждом уровне событие может быть "поглощено", чтобы не распространяться дальше. такой схемы мне хватает в 95% случаев.

а в оставшихся 5% я использую "аддоны". это значит, что к любому контролу можно прихреначить (на runtime) энное количество "обработчиков", которые будут перехватывать события, предназначенные окну, и делать что-то такое хитроуебищное... например, обслуживать drag-drop-ы или "резиновые контуры"...

и нахер мне тогда связи многие-ко-многим и переназначение реакций? если такое и понадобится, то раз в год, и раз в год мне не в падлу написать цикл.

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 06:04 pm (UTC)(link)
забавная схема. у меня обычно не «всплывают», а наоборот, «тонут».

однако же схема с «хуками» не есть красива, ящитаю. ну и Qt ещё умеет сам привинцивать сигналы на обработчики с соотв. именами. понятно, что это можно ручками один раз написать массажёра и всё, но лень же — уже написано.

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

[identity profile] psilogic.livejournal.com 2008-12-09 06:29 pm (UTC)(link)
мне кажется, всплывающие разумнее. вот прикинь: есть контрол, который обрабатывает "Enter". например, многострочное поле ввода multi-line-edit. тот же "Enter" может обработать диалог как "заставь сработать default button". если фокус стоит на multi-line-edit, то он обрабатывает Enter и "съедает" его. а если это не multi-line-edit, то клавишу потом получит диалог, который его выбросит, обработает или отдаст кому-то конкретному, если знает, кому (той же клавише по-умолчанию).

если же то же самое делать сверху-вниз, тогда ты должен рекурсивно опрашивать всех child-ов "тебе Enter не надо? а тебе Enter не надо?". получится перебор всех контролов вместо однократного прохода ветки снизу-вверх.

"не есть красива" - понятие субъективное. по-моему очень даже есть красива :) по мне так одно слово "moc" однозначно решает все вопросы на тему красоты - и не в пользу той библиотеки, которая этот moc использует :)

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

но как раз на этот случай у меня есть гибридная схема. :) у контрола может быть хоть миллион виртуальных обработчиков, но регулярно из них вызываются только несколько. остальные вызываются теми самыми аддонами.

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

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

в принципе, можно так все события обрабатывать, но тогда придется в конструкторе создавать эти аддоны-перебрасыватели. компромиссный вариант меня больше устраивает :)

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 06:37 pm (UTC)(link)
а разницы нет, в общем. в твоём случае сначала оно всплывёт до диалога, если сразу не съедят, а потом всё равно будет всем передаваться. в моём — сначала погрузится до контрола с фокусом, а если он не прожуёт — опять же пойдёт по рукам.

>но ведь такая функциональность нужна лишь немногим контролам, нафиг тогда
>вызывать эти функции у всех контролов?

правильно. у кого обработчика сигнала нет — тот и не откликнется. %-)

зыж что-то у нас хилый какой-то холивар получается.

[identity profile] psilogic.livejournal.com 2008-12-09 06:47 pm (UTC)(link)
а я не холиварю, я мыслю, может, ты че умное подскажешь ;)

ежели оно всплыло до диалога, то дальше все на этом. либо у диалога есть поинтер на что-то конкретное, дополнительное, тогда это еще плюс один вызов. а всем подряд сувать - какой смысл? в том примере прикинь, если в окне есть multi-line-edit и дерево (как в студии с редактором и деревом проекта), фокус стоит на дереве. деерву Enter не нужен, и зачем тогда совать Enter в первый попавшийся multi-line-edit? это уже излишество :)

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 07:00 pm (UTC)(link)
>ежели оно всплыло до диалога, то дальше все на этом.
это как это «всё»? это, то есть, диалог должен, например, знать о сущности «дефолтная кнопка» и какие события туда роутить? O_O

а enter надо всем предложить, вдруг он кому нужен? мультилайн умный, он глянет, что фокус не у него — и не станет трогать клаву. а дефолтная кнопка тупая, она увидит enter — и зажрёт, и пофигу ей на фокусы. именно чтобы такие гады не хавали чужие события, сначала его надо утопить до контрола с фокусом.

плюс подхода — диспетчер событий вообще не должен быть осведомлён ни о чём, кроме того, какое его дитё имеет фокус. и скидывает мессагу дитю. дитё в свою очередь тоже является диспетчером, смотрит на своих. и так далее. если событие никому в пень не надо — оно всплывёт на уровень выше и будет скормлено следующему контролу. и так пока контролы не закончатся, после чего ещё на уровень выше всплывёт. просто, как топором по яйцам. оверхэдом можно пренебречь, это гуя — тут даже с сотней контролов не выйдет схему затормозить (ну, у меня не выходило даже на 286-х %-).

[identity profile] psilogic.livejournal.com 2008-12-09 07:19 pm (UTC)(link)
[ то есть, диалог должен, например, знать о сущности «дефолтная кнопка» и какие события туда роутить? ]

именно. а почему бы и нет?

[ он глянет, что фокус не у него — и не станет трогать клаву ]

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

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 07:30 pm (UTC)(link)
>именно. а почему бы и нет?
а зачем ему знать о том, о чём знать не надо? мало ли, какой извращённый компонент я придумаю завтра — что, и такому обучать? это как раз нарушение красоты ооп и прямой путь к кодокаше. чем меньше объект знает о других — тем крепче спит программист.

>и каждый будет смотреть, а не у меня ли фокус, тварьли я дрожащая или право имею
>клавишу обрабать?

а в чём проблема? а вот есть такой себе скроллбар, который вообще, например, фокуса никогда не имеет. зато отлично обрабатывает клаву, потому что пришпандорен к нужному элементу. точнее, не обрабатывает, а преобразует события в «страница вверх» вместо «нажат pgup». отлично «херня не в фокусе» оживает, и более того — это ожидаемое юзером поведение. что, мне теперь диалоги и скроллбарам отдельно обучать? %-) или учить каждый scrollable component обрабатывать pgup самолично? а потом ещё и смотреть, не привинчены ли рядом скроллбары и их дёргать? нененене, Дэвид Блэйн, такая магия нам не нужна.

[identity profile] psilogic.livejournal.com 2008-12-09 07:22 pm (UTC)(link)
"ну, и ещё мелкий плюс " (C) - то, что контролы промеж собой не перегрызутся за клавиши :) папочка-диалог сам решит, кто достоин :)

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 07:32 pm (UTC)(link)
а он вообще этого знать не должен. тогда уже зачем вся эта объектная система? писать диалог монолитом, да и всё. какая разница, если по сути это и получается монолит, где контроллер обязан знать, что в него засунули? вся стройная система разваливается на процедурную простыню.

[identity profile] psilogic.livejournal.com 2008-12-09 07:44 pm (UTC)(link)
ну я имел в виду, что контроллер не знает, какие именно контролы в него засунули, он знает только их список, который из контролов сейчас в фокусе, а какой дефолтный. в принципе, я согласен, что яйцо можно разбивать и с тупого конца... ;)))))

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 07:50 pm (UTC)(link)
я предпочитаю, чтобы кубики как можно меньше друг о друге знали. в данном случае кубик знает, что в нём ещё какие-то кубики лежат, и знает, что у каждого кубика есть ::HandleEvent(). собственно, и всё. меньше знаешь — крепче спишь же.

[identity profile] psilogic.livejournal.com 2008-12-09 08:06 pm (UTC)(link)
в данном случае ты "знание о дефолтности" все равно можешь получить: если контрол, не будучи в фокусе, кушает Enter, это дефолтная кнопка :))

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 08:16 pm (UTC)(link)
не обязательно. может, это спецконтрол «йа питаюсь энтерами»? %-)

кстате. а как у тебя тогда хоткеи на кнопки сделаны? у меня кнопки их сами в себе и проверяют — рано или поздно до них доедет.

[identity profile] psilogic.livejournal.com 2008-12-09 08:50 pm (UTC)(link)
это сделано как у тебя - через перебор :) собственно, только для клавиатурных эвентов кое-какие переборы и понадобились. мышиные и прочие эвенты - достаточно прохода от точки срабатывания до корня. кстати, а зачем тебе такие переборы, если есть великая и могучая Qt? ;)

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 08:52 pm (UTC)(link)
затем, что это была консольная либа. %-)

[identity profile] psilogic.livejournal.com 2008-12-09 09:00 pm (UTC)(link)
как?! неужели вездесучий Qt еще не написан для консолей?! :)

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 09:05 pm (UTC)(link)
для пингвинов можно извратнуться. для вантуза — увы. %-)

а вообще-то либа на Delphi была. %-)

[identity profile] http://technorati.com/people/technorati/ketmar/ (from livejournal.com) 2008-12-09 07:02 pm (UTC)(link)
ну, и ещё мелкий плюс — легко реализуется event preview/postview.