огнена маймуна
TChromium в FireMonkey
Компонентът TChromiumFMX от официалното събрание работи доста добре във FireMonkey (в XE2), но дори не се компилира във FMX2. Трябваше да разбера малко как работи и да го поправя. За щастие не се наложиха големи промени.
Във FMX2 две неща, от които се нуждае компонентът, са променени.
Първо, TBitmap вече няма свойства ScanLine и StartLine. Директният достъп до съдържанието на TBitmap е преработен (чудя се защо?) и вече е достъпен чрез класа TBitmapData, който връща метода TBitmap.Map.
Е, вторият, по-известен - Platform.* вече не е, сега трябва да получите желания интерфейс чрез TPlatformServices.GetPlatformService. Тук всичко е доста просто и няма никакви проблеми.

Nakey Monkey
Джейсън Саутуел предлага да се разработи набор от обвивки на FireMonkey за собствени Windows/OSX контроли и събира пари за това. Той планира да събере 20 000 долара като начало.
Идеята е ясна. Съществуващите компоненти на FireMonkey се изчертават с помощта на инструменти на Delphi почти от нулата, което, от една страна, до голяма степен гарантира тяхната крос-платформа, но от друга страна, в резултат на това получаваме компоненти, които не изглеждат съвсем естествени и в двете поддържани в момента операционни системи. И това не е толкова лошо - в допълнение към външния вид, трябва самостоятелно да развиете логиката на тези компоненти. Например RichEdit е доста сложен и повтарянето на логиката му в FireMonkey не е тривиална задача. И VCL, и CLX не са изобретили велосипеди, а са използвали готови.
На резонния въпрос „защо NakeyMonkey успява в това, което Kylix CLX не успя на времето си?“ Джейсън отговаря, че проблемът на CLX е бил използването на допълнителен междинен софтуер под формата на Qt, NakeyMonkey няма да бъде обвързан с цикъла на разработка идруги капризи на трета библиотека, но като цяло ще има всички трудности и трудности на CLX.
какви са вашите мнения Как би могло това да се впише в стилистичната идеология на FireMonkey?
Ще критикувам малко FireMonkey
Продължавайки предишната публикация, нека поговорим малко повече за FireMonkey. Много неприятно за мен е усещането, че при разработването на стандартни компоненти никой не е мислил, че някой ще ги наследи, ще се опита да ги разшири и промени поведението им. В сравнение с VCL, в момента има много, много малко налични компоненти на FireMonkey. И ми се струва, че съдбата на рамката днес до голяма степен зависи от удобството на разработването на нови компоненти.
Ще дам конкретен пример.
Продължавам да работя с TTabControl. Този път искам да мога да поставя компоненти в неклиентската област. Признавам, искам да повторя функционалността на браузърите - да поставят бутон за отваряне на нови раздели вдясно от тях.
Не би трябвало да има проблем, тъй като във FireMonkey всички стилизирани контроли могат да бъдат контейнери за други контроли. Особеността на тази конкретна ситуация е, че на това място просто няма нищо, върху което да се поставят компоненти.
Изпълнението е очевидно. Имаме нужда от контрол с най-прост стил (да речем, само TLayout), ще го поставим на TTabControl и ще го позиционираме по аналогия с разделите. Нека ви напомня, че разделът тук е само самият бутон, но аз просто искам да съм отдясно на бутоните.
Нека да разгледаме метода TTabControl.Realign. Методът е дълъг, но не можете да изхвърлите думи от песен. Можете да превъртите назад, малко по-късно ще преразкажа същността му накратко.
Тук по принцип няма магия. Методът като цяло прави само три важни неща:
- Преминава през списъка с раздели, указвайкимаксимална височина на раздела (MaxHeight);
- Позиционира „тялото“ на TTabControl в достъпното за него пространство, измествайки горната му част надолу със същите тези MaxHeight пиксели;
- Така отгоре остава ивица свободно място и лесно можете да поставите там бутони за раздели.
Към всичко това сега трябва да добавя настройка на позицията на моя нов неклиентски панел. Какво е необходимо за това? Стойността MaxHeight, за да знаете височината на даденото пространство и координатите на най-десния бутон. Освен това трябва да направите малки промени в логиката на поставяне на бутони, забранявайки им да заемат цялата ширина на TTabControl - разделите не трябва да могат да правят ширината на неклиентския панел по-малка от някаква зададена стойност.
И честно казано, не виждам начин да го направя добре. Претоварването на Realign няма да помогне. В резултат на това ще трябва да дублирате доста прилични парчета код по отношение на обема. Например MaxHeight ще бъде изчислен два пъти. Това, разбира се, е дреболия, но няма да добави скорост, но може да добави грешки.
Няма да предложа нищо глобално, само ще покажа до какво може да доведе един малък и много прост рефакторинг. Нека си признаем, че сега Realign, ако не нарушава „принципа на единната отговорност“, очевидно балансира на ръба.
Така нещо като:
Общо 4 нови метода със стар код.Всеки от които трябва да е виртуален. Тогава цялата ми работа ще се сведе до претоварване на метода AlignTabs. Стойността MaxHeight ще бъде налична в него и бих могъл да променя логиката на разположението на разделите, без да засягам всичко останало, и, разбира се, да добавя нов панел.
За съжаление описаният проблем не е частен случай. Ще ви покажа още един пример.
TMemo в FireMonkeyреализирани по доста интересен начин. Текстът се рисува с обикновен FillText върху платното, а за позициониране на каретката се използва съответно изчисляването на височината на линиите и ширината на фрагмента от текущия ред. Възможностите за персонализиране изглеждат безкрайни.
Стори ми се интересно да се опитам да внедря просто подчертаване на синтаксиса. Рисуването е просто: на манипулатора OnPaint на платното се присвоява методът DoContentPaintWithCache, той извиква DoContentPaint, за да рисува, когато е необходимо, и когато е възможно, просто рисува старата картина от кеша.
Проблемите започват с това, че и двете функции не са виртуални. Тоест, не мога просто да претоваря DoContentPaint, първо трябва да копирам кода DoContentPaintWithCache в моето дете, като заменя извикването на DoContentPaint с моя нов метод за рисуване. И след това инсталирайте това копие с манипулатора OnPaint. Просто имаше дублиране
Но това не е целият проблем. DoContentPaint е голям метод (
120 реда) и просто трябва да заменя простия FillText в него с нещо малко по-сложно. Тоест отново трябва да копирате целия код, като замените няколко извиквания в него.
Ако отидете по-далеч и промените не само цвета на отделните думи, но и ги направите удебелени (всъщност промените ширината), ще трябва леко да промените логиката на позициониране на каретката. Методът TextWidth, който се използва при изчисляване на позицията на каретката в пиксели, разбира се, не взема предвид тези нюанси в текущата реализация. Но този метод също не е виртуален. Между другото, дори е частно. Необяснимо.
Отказ от отговорност: Не искам да бъда разбран погрешно, всъщност харесвам идеята за FireMonkey. Но сега доста си ударих главата в стените. Пожелавам на Embarcadero търпение и късмет при фината настройка на тази рамка.