пятница, марта 11, 2016

Delphi ARC такой ARC...

Проверил на Андроиде. Delphi 10 Seattle Update 1.

Procedure Run;
Var

 Proc : Procedure Of Object;

Begin

 TObj.Create('1');              // will be destroyed
 TObj.Create('2').Test;         // will be never destroyed
 Proc := TObj.Create('3').Test; // will be never destroyed

End; 


А будущий компилятор для линукса обещает быть ARC enabled по дефолту...
[RSP-13934]

вторник, марта 08, 2016

Позитивчик из стана FreePascal

Вчера появилась новость о том, что во FreePascal реализованы перегружаемые операторы класса для инициализации и финализации. Ждём скорейшего интегрирования в транк, а также возможность перегрузки оператора копирования. Ура! Кстати, запрос на аналогичную функциональность в Delphi уже 10 лет висит в QC.

четверг, ноября 06, 2014

Пространства имен. Неработающая фича Delphi.

В процессе очередного рефакторинга обнаружилось, что пространства имен в Delphi, которые для нативных дельфей стали доступны еще в Delphi 2006, если не раньше, попросту не работают. Как именно они не работают я отписал в QC#128737. А также оформил небольшой фич-риквест QC#128740. Не сочтите за труд, поддержите голосованием.

воскресенье, апреля 13, 2014

Эмуляция перегружаемых дефолтных свойств во FreePascal 2.7.1

В настоящий момент FreePascal не поддерживает перегружаемые дефолтные свойства (на что есть соответствующий запрос), поддержка которых появилась в Delphi после седьмой версии. Нельзя сказать, что это киллер-фича, но иногда она бывает очень полезной. Однако, с появлением поддержки улучшенных записей (advanced records) и перегрузки операторов появилась возможность немного сгладить этот досадный недостаток. От слов к коду:

program project1;

{$IFNDEF FPC}

{$APPTYPE CONSOLE}
{$DEFINE HAS_OVERLOADABLE_DEFAULT_PROPERTIES}

{$ELSE}

{$MODE DELPHI}

{$ENDIF}

Type

//
TContainer = Record

{$IFNDEF HAS_OVERLOADABLE_DEFAULT_PROPERTIES}

Strict Private

Type

//
StringNameOrIntegerId = Record

FKind : (ikName, ikId);
FName : String;
FId : Integer;

Class Operator Implicit(Const AName : String) : StringNameOrIntegerId;
Class Operator Implicit(Const AId : Integer) : StringNameOrIntegerId;

End;
//

{$ENDIF}

Private

Function GetItemByName(Const AName : String) : TObject;
Function GetItemById(Const AId : Integer) : TObject;

{$IFNDEF HAS_OVERLOADABLE_DEFAULT_PROPERTIES}

Function GetItem(Const ANameOrId : StringNameOrIntegerId) : TObject;

{$ENDIF}

Public

{$IFDEF HAS_OVERLOADABLE_DEFAULT_PROPERTIES}

Property Items[Const AName : String] : TObject Read GetItemByName; Default;
Property Items[Const AId : Integer] : TObject Read GetItemById; Default;

{$ELSE}

Property Items[Const ANameOrId : StringNameOrIntegerId] : TObject Read GetItem; Default;

{$ENDIF}

End;

{$IFNDEF HAS_OVERLOADABLE_DEFAULT_PROPERTIES}

{ TContainer.StringNameOrIntegerId }

//
Class Operator TContainer.StringNameOrIntegerId.Implicit(Const AName : String) : StringNameOrIntegerId;
Begin

Result.FKind := ikName;
Result.FName := AName;

End;
//

//
Class Operator TContainer.StringNameOrIntegerId.Implicit(Const AId : Integer) : StringNameOrIntegerId;
Begin

Result.FKind := ikId;
Result.FId := AId;

End;
//

{$ENDIF}

{ TContainer }

//
Function TContainer.GetItemByName(Const AName : String) : TObject;
Begin

Result := TObject(1); // stub

End;
//

//
Function TContainer.GetItemById(Const AId : Integer) : TObject;
Begin

Result := TObject(2); // stub

End;
//

{$IFNDEF HAS_OVERLOADABLE_DEFAULT_PROPERTIES}

//
Function TContainer.GetItem(Const ANameOrId : StringNameOrIntegerId) : TObject;
Begin

Case ANameOrId.FKind Of

ikName : Result := GetItemByName(ANameOrId.FName);
ikId : Result := GetItemById(ANameOrId.FId);

End;

End;
//

{$ENDIF}

Var

cnt : TContainer;

begin

Assert(cnt['name'] = TObject(1));
Assert(cnt[1024] = TObject(2));

WriteLn('Overloadable default properties works fine!');
ReadLn;

end.


 



Это готовый пример который можно собрать в Delphi и FreePascal 2.7.1. Из кода видно, что проблему решает новый тип – улучшеная запись выступающий в качестве типа индекса дефолтного свойства и инкапсулирующий реальный тип индекса. Прикладной код, при этом, остается полностью совместимым с Delphi и возможной поддержкой перегружаемых дефолтных свойств во FreePascal в будущем.



Данный метод также может пригодится в случае, когда некое свойство (не обязательно перегружаемое и дефолтное) должно принимать значения ограниченного числа типов, т.е. это может быть полезно не только для FreePascal, но и для Delphi.

четверг, марта 20, 2014

QPS в действии?

18 марта, баг-репорт QC#121566, которому были посвящены четыре поста “с ассемблером”, получил статус Resolved. Это, конечно, еще не Closed, но... Будем надеяться :) Хотя сам по себе факт решения проблемы довольно будничный, но не упомянуть о нем после широкой огласки было-бы несправедливо. Хочу поблагодарить всех, кто проголосовал, а также тех, кто способствовал распространению информации о данной проблеме. Спасибо.

Напомню, что в обновленной дорожной карте RAD Studio, Delphi and C++Builder на 2014 год, одним из пунктов декларируется QPS (Quality, Performance, Stability). Давно пора!

вторник, марта 11, 2014

среда, февраля 05, 2014

Delphi. Ненависть 2. 64-битная версия

Пост-продолжение Delphi. Ненависть 2.

------------------------------ Delphi XE2 Update 4 Hotfix 1 x64:
Project1.dpr.68: Utils.Namespace.CompareString(S1, S2);
0000000000426680 488D4D58         lea rcx,[rbp+$58]
0000000000426684 488B15BDEB0000   mov rdx,[rel $0000ebbd]
000000000042668B E86020FEFF       call @UStrLAsg
0000000000426690 488D4D50         lea rcx,[rbp+$50]
0000000000426694 488B15B5EB0000   mov rdx,[rel $0000ebb5]
000000000042669B E85020FEFF       call @UStrLAsg
00000000004266A0 488B4D58         mov rcx,[rbp+$58]
00000000004266A4 488B5550         mov rdx,[rbp+$50]
00000000004266A8 E82349FFFF       call CompareStr
Project1.dpr.69: Utils.Namespace.SameString(S1, S2);
00000000004266AD 488D4D48         lea rcx,[rbp+$48]
00000000004266B1 488B1590EB0000   mov rdx,[rel $0000eb90]
00000000004266B8 E83320FEFF       call @UStrLAsg
00000000004266BD 488D4D40         lea rcx,[rbp+$40]
00000000004266C1 488B1588EB0000   mov rdx,[rel $0000eb88]
00000000004266C8 E82320FEFF       call @UStrLAsg
00000000004266CD 488D4D38         lea rcx,[rbp+$38]
00000000004266D1 488B5548         mov rdx,[rbp+$48]
00000000004266D5 E81620FEFF       call @UStrLAsg
00000000004266DA 488D4D30         lea rcx,[rbp+$30]
00000000004266DE 488B5540         mov rdx,[rbp+$40]
00000000004266E2 E80920FEFF       call @UStrLAsg
00000000004266E7 488B4D38         mov rcx,[rbp+$38]
00000000004266EB 488B5530         mov rdx,[rbp+$30]
00000000004266EF E8DC48FFFF       call CompareStr
------------------------------ Delphi XE5 Update 2 x64:
Project1.dpr.68: Utils.Namespace.CompareString(S1, S2);
0000000000426F94 488D4D78         lea rcx,[rbp+$78]
0000000000426F98 488B1581F20000   mov rdx,[rel $0000f281]
0000000000426F9F E88C23FEFF       call @UStrLAsg
0000000000426FA4 488D4D70         lea rcx,[rbp+$70]
0000000000426FA8 488B1579F20000   mov rdx,[rel $0000f279]
0000000000426FAF E87C23FEFF       call @UStrLAsg
0000000000426FB4 90               nop
0000000000426FB5 488B4D78         mov rcx,[rbp+$78]
0000000000426FB9 488B5570         mov rdx,[rbp+$70]
0000000000426FBD E86E34FFFF       call CompareStr
0000000000426FC2 89453C           mov [rbp+$3c],eax
0000000000426FC5 90               nop
0000000000426FC6 488D4D78         lea rcx,[rbp+$78]
0000000000426FCA E8411EFEFF       call @UStrClr
0000000000426FCF 488D4D70         lea rcx,[rbp+$70]
0000000000426FD3 E8381EFEFF       call @UStrClr
Project1.dpr.69: Utils.Namespace.SameString(S1, S2);
0000000000426FD8 488D4D58         lea rcx,[rbp+$58]
0000000000426FDC 488B153DF20000   mov rdx,[rel $0000f23d]
0000000000426FE3 E84823FEFF       call @UStrLAsg
0000000000426FE8 488D4D50         lea rcx,[rbp+$50]
0000000000426FEC 488B1535F20000   mov rdx,[rel $0000f235]
0000000000426FF3 E83823FEFF       call @UStrLAsg
0000000000426FF8 488D4D68         lea rcx,[rbp+$68]
0000000000426FFC E80F1EFEFF       call @UStrClr
0000000000427001 488D4D60         lea rcx,[rbp+$60]
0000000000427005 E8061EFEFF       call @UStrClr
000000000042700A 488D4D48         lea rcx,[rbp+$48]
000000000042700E E8FD1DFEFF       call @UStrClr
0000000000427013 488D4D40         lea rcx,[rbp+$40]
0000000000427017 E8F41DFEFF       call @UStrClr
000000000042701C 90               nop
000000000042701D 488D4D68         lea rcx,[rbp+$68]
0000000000427021 488B5558         mov rdx,[rbp+$58]
0000000000427025 E80623FEFF       call @UStrLAsg
000000000042702A 488D4D60         lea rcx,[rbp+$60]
000000000042702E 488B5550         mov rdx,[rbp+$50]
0000000000427032 E8F922FEFF       call @UStrLAsg
0000000000427037 90               nop
0000000000427038 488B4D68         mov rcx,[rbp+$68]
000000000042703C 488B5560         mov rdx,[rbp+$60]
0000000000427040 E8EB33FFFF       call CompareStr
0000000000427045 894534           mov [rbp+$34],eax
0000000000427048 90               nop
0000000000427049 488D4D68         lea rcx,[rbp+$68]
000000000042704D E8BE1DFEFF       call @UStrClr
0000000000427052 488D4D60         lea rcx,[rbp+$60]
0000000000427056 E8B51DFEFF       call @UStrClr
000000000042705B 837D3400         cmp dword ptr [rbp+$34],$00
000000000042705F 0F94C0           setz al
0000000000427062 88453B           mov [rbp+$3b],al
0000000000427065 90               nop
0000000000427066 488D4D58         lea rcx,[rbp+$58]
000000000042706A E8A11DFEFF       call @UStrClr
000000000042706F 488D4D50         lea rcx,[rbp+$50]
0000000000427073 E8981DFEFF       call @UStrClr
0000000000427078 488D4D68         lea rcx,[rbp+$68]
000000000042707C E88F1DFEFF       call @UStrClr
0000000000427081 488D4D60         lea rcx,[rbp+$60]
0000000000427085 E8861DFEFF       call @UStrClr
000000000042708A 488D4D48         lea rcx,[rbp+$48]
000000000042708E E87D1DFEFF       call @UStrClr
0000000000427093 488D4D40         lea rcx,[rbp+$40]
0000000000427097 E8741DFEFF       call @UStrClr
------------------------------ FreePascal 2.7.1. x64:
project1.lpr:68                           Utils.Namespace.CompareString(S1, S2);
000000010000158A 488b157fda0100           mov    0x1da7f(%rip),%rdx        # 0x10001f010
0000000100001591 488b0d68da0100           mov    0x1da68(%rip),%rcx        # 0x10001f000
0000000100001598 e843e40000               callq  0x10000f9e0 <SYSUTILS_$$_COMPARESTR$ANSISTRING$ANSISTRING$$LONGINT>
project1.lpr:69                           Utils.Namespace.SameString(S1, S2);
000000010000159D 488b156cda0100           mov    0x1da6c(%rip),%rdx        # 0x10001f010
00000001000015A4 488b0d55da0100           mov    0x1da55(%rip),%rcx        # 0x10001f000
00000001000015AB e830e40000               callq  0x10000f9e0 <SYSUTILS_$$_COMPARESTR$ANSISTRING$ANSISTRING$$LONGINT>
00000001000015B0 85c0                     test   %eax,%eax
00000001000015B2 0f94c0                   sete   %al

пятница, января 31, 2014

Firemonkey, которая гуляет сама по себе.

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

Воспроизведено на устройстве Huawei Ascend Mate, Android 4.1.2, ланчер EmotionUI 1.5.

Проект на котором очень хорошо воспроизводятся эти эффекты можно взять тут (прямая ссылка).

На видео видно, что несмотря на фантомные срабатывания, когда к устройству даже не прикосаешься, само приложение никак не реагирует на прикосновения пальца (это бывает не всегда, и иногда оно таки реагирует). Более того, перестают реагировать даже системные навигационные кнопки. Все это безобразие можно прекратить только нажатием аппаратной кнопки выключения.

Нужно заметить, что ни в одном другом приложении, ни основанных на SDK, ни на NDK таких эффектов не наблюдается. К телефону вообще нет ни малейших претензий. Воспроизводится это только в Firemonkey-приложениях.

QC#122138

понедельник, января 20, 2014

Если хочешь быть здоров…

…закаляйся!

IMG_20140119_115636

IMG_20140119_115645

Уже пятый год, на Крещение, ходим с друзьями купаться. Вчера было здорово. Погода прекрасная: легкий морозец (-22 градуса) и едва заметный снежок.

понедельник, января 06, 2014

Delphi. Ненависть 2.

В посте Delphi. Ненависть. я показал как деградировал кодогенератор дельфей. Сегодня покажу еще раз, только уже с кодом на котором проблема воспроизводится.

воскресенье, декабря 29, 2013

Delphi XE5 Update 2. S.S.D.D.

Вот, наконец-то, и я добрался (несколько припозднился, но на то были причины) до ощупывания Delphi с поддержкой Android. С самого начала было ясно, что качественной эта поддержка не будет, а потому нет смысла сразу кидаться покупать какое-либо Android-устройство. Но в планах уже значиналось приобретение нового смартфона на замену дышавшей на ладан старенькой Nokia. С моделью я определился через несколько дней после выхода Delphi XE5 (стимул всё-таки), и как выяснилось практически сразу, с выбранной моделью у Delphi проблемы (точнее с графическим процессором используемом в данном аппарате). Но, телефон должен нравится мне, а не Delphi, поэтому выбора своего я решил не менять (хотя посматривал и на Lenovo K-900, но с тем у Delphi вообще фатальная несовместимость) и надеяться на скорый фикс этого бага. В Update 2 баг таки пофиксили. Ура. Тестируем новую обезьяну, ой, простите, теперь это уже FM Platform (не хухры-мухры, но попробуйте кроссплатформенно послать SMS’ку или погудеть виброй, так сразу поймете ценность этого “Platform” :))

суббота, октября 12, 2013

Кушайте, не обляпайтесь.

Сегодня в ридере появилась статья “Delphi штурмует Android. Беседуем с Всеволодом Леоновым о Delphi XE5” рассказывающая о победах и завоеваниях. Такое всегда интересно почитать. Я позволю себе процитировать оттуда небольшой фрагмент:

- Технологии FireMonkey уже несколько лет. Вроде все более менее становится стабильным и уже не так страшно применять новинку для продакшн приложений. По прошествии этого временного промежутка вы можете сказать, что технология удалась? Нашла ли она свою аудиторию и какие нововведения следует ожидать в обозримом будущем?

Что технология удалась, стало заметно, к сожалению, лишь сейчас, если мы смотрим на неё глазами разработчиков. Только сейчас программисты стали реально интересоваться Платформой приложений FM (бывшая FireMonkey), когда увидели всю её мощь для мобильной разработки под Android. И это несмотря на то, что архитектурно она была заложена и технологически реализована в релизе XE2. Например, российский проект www.sphere-online.ru – многоцелевая платформа онлайн-коммуникаций. Команда выбрала Платформу FM, т.к. изначально хотела сделать мульти-платформенное решение для Windows и Mac OS, причем с интерфейсом высшего качества. На следующем после XE2 релизе XE3 данная компания сделала мульти-платформенную систему, а что может быть лучшим доказательством успешности технологии, как ни реализация на её основе реального проекта!? Теперь данная команда благодарит сама себя за правильный выбор средства разработки в своё время и готовит мобильную поддержку.

 

В общем, я сходил по данной ссылке… Никакой многоцелевой платформы онлайн-коммуникаций там нет, есть редирект на онлайн-игру “Сфера-перерождение”. Думаю, ну мало-ли, может их сейчас принято называть многоцелевыми коммуникационными платформами. В общем, скачал клиент дабы посмотреть чего там на FMX наваяли. Оказалось, что FMX’ом там и не пахнет. Исполняемые модули, коих две штуки, собраны компилятором MS VC++, и россыпь dll’ей тоже ни коим боком к FMX не относится. Так то. А народ в комментариях радуется, дескать жива курилка. Хотел прямо там вопрос задать – что мол за дела - да у них для этого регистрироваться нужно. В общем вот. В меню сегодня лапша.

 

Обновление от 16.10.2013.

Так, похоже имела место быть чья-то невнимательность, из-за которой в статье была указана неправильная ссылка. А я уже успел о Всеволоде плохо подумать :) Спасибо Роману Янковскому за изыскания. Правильная ссылка вот http://www.sphere-live.com/ и там действительно коммуникационный софт с FMX-интерфейсом.

 

Но я же не зря ходил по тем ссылкам, я хотел посмотреть на интерфейс высшего качества о котором говорится в статье. Итак, кратко - под интерфейсом высшего качества имеется ввиду FMX-стиль “Jet” из Premium Style Pack (это тот, где все черное-черное). Кому-то сливающаяся чернота нравится, кому-то нет.

Теперь по порядку. Первый запуск на хостовой машине c Windows 7 x64 закончился ничем:

sphere_at_start_on_host

Следующие попытки я делал уже под виртуальной Windows 7 x86. Запуск прошел успешно. Но в окне регистрации, после выбора русского языка, снова сюрприз:

sphere_av

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

sphere_gui

Потребление памяти на этом этапе составляло примерно 140MB, что довольно много для такого софта, особенно если учесть, что пользоваться я им даже не начал. Реакция интерфейса на действия пользователя по FMX-овски неспешная, если не сказать тормозная. Это уж точно не высший класс. В конце-концов приложение пришлось прибить т.к. при выходе случилось страшное (я долго ждал завершения, но так и не дождался):

sphere_at_exit

пятница, мая 10, 2013

Delphi. Ненависть.

Код (вызов представляющий собой каскад двух inlined методов):

xv.Initialize(bin.Instance);


Turbo Delphi 2006 Explorer генерирует:



XmlRpcDeserializerTest.pas.2634: xv.Initialize(bin.instance);
00526489 8D9524FFFEFF lea edx,[ebp-$000100dc]
0052648F 8D45E8 lea eax,[ebp-$18]
00526492 E88DA8FAFF call XmlRpcBinary.GetInstance
00526497 8B8524FFFEFF mov eax,[ebp-$000100dc]
0052649D 8945B0 mov [ebp-$50],eax
005264A0 A154784C00 mov eax,[$004c7854]
005264A5 50 push eax
005264A6 8D8558FFFFFF lea eax,[ebp-$000000a8]
005264AC B107 mov cl,$07
005264AE 8B55B0 mov edx,[ebp-$50]
005264B1 E89E37FAFF call XmlRpcValue.SetValueIntf


Delphi XE2 - XE4 генерирует:



XmlRpcDeserializerTest.pas.2634: xv.Initialize(bin.instance);
006C9E77 8D955CFFFEFF lea edx,[ebp-$000100a4]
006C9E7D 8D85C4FFFEFF lea eax,[ebp-$0001003c]
006C9E83 E8683DF6FF call XmlRpcBinary.GetInstance
006C9E88 8B9D5CFFFEFF mov ebx,[ebp-$000100a4]
006C9E8E 8D85E4FFFEFF lea eax,[ebp-$0001001c]
006C9E94 E8973FD4FF call @IntfClear
006C9E99 33C0 xor eax,eax
006C9E9B 55 push ebp
006C9E9C 684D9F6C00 push $006c9f4d
006C9EA1 64FF30 push dword ptr fs:[eax]
006C9EA4 648920 mov fs:[eax],esp
006C9EA7 8D85E4FFFEFF lea eax,[ebp-$0001001c]
006C9EAD E87E3FD4FF call @IntfClear
006C9EB2 33C0 xor eax,eax
006C9EB4 55 push ebp
006C9EB5 682D9F6C00 push $006c9f2d
006C9EBA 64FF30 push dword ptr fs:[eax]
006C9EBD 648920 mov fs:[eax],esp
006C9EC0 8D85E4FFFEFF lea eax,[ebp-$0001001c]
006C9EC6 8BD3 mov edx,ebx
006C9EC8 E87B3FD4FF call @IntfCopy
006C9ECD 33C0 xor eax,eax
006C9ECF 55 push ebp
006C9ED0 680D9F6C00 push $006c9f0d
006C9ED5 64FF30 push dword ptr fs:[eax]
006C9ED8 648920 mov fs:[eax],esp
006C9EDB A10C3B6200 mov eax,[$00623b0c]
006C9EE0 50 push eax
006C9EE1 8D85A0FFFEFF lea eax,[ebp-$00010060]
006C9EE7 B107 mov cl,$07
006C9EE9 8B95E4FFFEFF mov edx,[ebp-$0001001c]
006C9EEF E898C7F5FF call XmlRpcValue.SetValueIntf


Это п#$%&ц. Зарепортить не могу т.к. воспроизвести на другом коде не получается. Но подобное есть еще в паре мест, и тоже с разворачиванием inlined методов.

четверг, мая 02, 2013

Delphi XE4. Чем дальше, тем страшнее.

Кажется, у Embarcadero уже вошло в привычку выпускать сырые бета-версии и называть их релизами. Чтож, они испекли еще один. Судя по всему, делался он в дикой спешке – иначе объяснить настолько отвратительное качество просто нечем.

 

Firemonkey. Одно лечим, другое калечим.

В обезьяне произошли некоторые приятные изменения – анимация стала работать заметно лучше – и дело тут не в увеличенном вдвое фреймрейте - спасибо разделяемому RTTI-кэшу. Однако, для отсчетов временных интервалов по прежнему используется тип с малой точностью, поэтому на системах с большим аптаймом снова будут рывки.

Padding и Margins поменяли поведение на противиположное. Некоторые контролы переехали в другое пространство имен. В общем, переделки пользователям FMX, если такие отчаянные есть, обеспечены.

Формы FMX разучились сворачиваться в панель задач – клик по кнопке в панели ни к чему не приводит. Сворачивать можно только кнопкой в заголовке окна, но при этом форма сворачивается не в панель задачь, а в левый нижний угол над панелью.

В дизайнере не меняется шрифт у TText и TLabel. То есть изменение размера действует, а вот изменение названия нет.

Поправили TPath, теперь он справляется с довольно сложными контурами. Однако, TPath.WrapMode = pwFit работает некорректно. Сглаживание контуров под XP так и не сделали (она хоть и старушка, но все же третья по популярности ОС). Кстати, со сглаживанием вообще странность. В редакторе свойства TPath.Data контур оказывается сглаженным:

data_editor_normal

но стоит изменить размер окна, как сглаживание исчезает:

data_editor_resized

Поломали TreeView. Если у дерева вызвать метод TreeView.ExpandAll список узлов превращается в кашу (слева пример собранный в XE3, справа в XE4):

expanded_treeviews

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

пятница, декабря 07, 2012

Блеск и нищета Firemonkey²

Блеск

В Delphi XE3 у Firemonkey появилась возможность стилизовать неклиентскую область окон приложения. Для этого используются новые имена стилей: для Windows это windowborderstyle и toolwindowstyle, для Mac OS используется единственный стиль macborderstyle. Информации, как создать такие стили нет, во всяком случае я не нашел, поэтому всё что будет написано дальше является результатом исследования кода класса TWindowBorder и его потомков под каждую платформу. В общем, можно сказать, что создать собственный стиль неклиентской области дело довольно простое. Стиль подразумевает наличие некоторых предопределенных элементов (например ‘client’ отвечает за клиентскую область окна, а ‘title’ за его текстовый заголовок) из которых формируется внешний вид окна. Так же имя элемента стиля отвечает за обозначение действия какой-либо области окна. Например элементы c именем стиля ‘left’ и ‘right’ отвечают за изменение горизонтального размера окна, а ‘caption’ за его перемещение (элементов с одинаковым именем стиля может быть несколько, что в результате даст несколько зон отвечающих за одно и то же действие) То есть при клике на этих элементах будет выполняться соответствующее им действие. В общем, кто имел опыт работы с WinAPI, в части обработки оконных сообщений, наверняка провели параллель с такой вещью, как HITTEST, и оказались правы – механизм работает один-в-один. Это был блеск. Теперь о нищете.

Нищета

Воодушевившись открывшимися новыми возможностями я решил сделать стиль имитирующий окна Mac OS X Leon. За основу был взят незамысловатый скриншот:

pic14

и еще несколько изображений окон, где присутствовали кнопки в заголовке окна. Я не ставил себе целью сделать сразу полнофункциональный стиль, для начала хотелось добиться схожести с оригиналом. Вооружившись дизайнером стилей и в очередной раз убедившись, что пользоваться оным невозможно, было решено дизайнить стиль прямо на форме (ведь любой стиль это просто набор компонентов). Затем с формы стиль был скопирован в файл macosx.style и загружен в компонент класса TStyleBook, который был назначен форме. В редакторе стилей созданный стиль выглядел вот так:

styledesigner

Сглаживания на кнопке нет т.к. делал я все под Windows XP, а у Firemonkey на этой ОC сглаживание не работает (работало до Delphi XE2 Update 4 hotfix 1, но хотфиксом его сломали да так и не починили). Для создания эффекта тени пришлось генерировать картинку в GIMP т.к. стандартный эффект TShadowEffect такую тень отрисовать не способен (при значении свойства Softness равном единице тень уже имеет видимую глазу структуру, а при значениях больше единицы и вовсе превращается в клетчатое пятно). Но с картинкой возникает проблема. При изменении размера окна тень должна растягиваться без артефактов поэтому просто масштабировать картинку нельзя, её нужно делить на области: четыре имеющих постоянный размер (расположены в углах), две растягивающиеся горизонтально и две растягивающие вертикально. Итого получается восемь частей. Каждую такую часть можно было представить компонентом TImage в который был бы загружен файл соответствующей части изображения. Однако, в Delphi XE3, для поддержки растровых стилей Firemonkey, появился класс TSubImage способный отрисовывать указанную область изображения на которое он ссылается. Это удобнее, чем делать множество файлов. Но, этот класс не доступен в дизайнере, поэтому мне пришлось установить в IDE пакет регистрирующий его. В общем, после некоторого непредвиденного траха с пакетом, тень была готова. Заголовок с кнопкой и клиенсткую область сделать труда не составило. Хотя нет, подобрать градиент для кнопки было сложно т.к. элементы выделения (белые кружочки для изменения размеров) полностью перекрывали маленькую кнопку и изменяющийся градиент было не видно :) В результате схожесть не попиксельная, но довольно близка к оригиналу. Итак, стиль готов, первый запуск:

styledwindowblackshadow

Легкое недоумение. Пробую максимизировать окно, оно максимизируется так, как будто тень является клиентской областью т.е. я вижу не распахнутую на весь экран клиентскую область, а клиентскую область в окружении черной рамки. Хорошо, с максимизацией разберемся как нибудь позже, но почему тень не прозрачная… Я же помню, что у меню были прозрачные тени. Ищу в файле стилей стиль для меню (menuviewstyle). Вижу, что тень сделана с помощью эффекта TShadowEffect, но место под неё зарезервировано с помощью свойств Margin и Padding у элементов стиля. Попробовал и я у своей тени выставить отрицательный Padding, вот что из этого вышло:

styledwindow

Тень совсем пропала, а кроме этого на каждое изменение размеров окна генерируется четыре исключительных ситуации EZeroDivide. В общем трюк не сработал. Начал смотреть, что же там происходит под капотом модуля FMX.Platform.Win отвечающем за взаимодействие с платформой Windows. А там все печально. Оказалось, что по изображению полученному отрисовкой стиля формируется регион (регион в терминологии Win32) и назначается окну. Всё, прощай прозрачная тень, прощайте сглаженные уголки окна и да здравствуют зазубрины :( Но, как же, тогда отрисовывается тень у меню? А для меню используются композитные окна (см. TFrom.Transparency). В общем, тоска зеленая :(

понедельник, декабря 03, 2012

iPhone “slide to unlock” animation средствами Firemonkey. DelphiXE2.

Как бы кто ни относился к Apple, одно признают все – эти парни умеют делать красиво. Их “красота” заключается в не пергруженных деталями интерфейсах и изысканных мелочах. Одной из таких мелочей является анимация элемента разблокировки экрана (кто не видел, погуглите slide to unlock animation). Как только вышла Delphi XE2 я сразу попробовал сделать подобный эффект средствами Firemonkey. Тогда, получив удовлетворительный результат, я не стал описывать его т.к. думал, что следующая версия Firemonkey позволит реализовать этот эффект не написав ни строчки кода. Этого, увы, не случилось. Более того, в Delphi XE3, классы TText и TLabel лишились свойства Fill, что сделало невозможным применение каких-либо вариантов раскраски текста. Поэтому публикую вариант для Delphi XE2.

Вот что у меня вышло:

spotlight_effect

Реализация очень простая. В качестве “раскраски” текста применяется битмап в который отрисовывается прямоугольник серого цвета с анимированным градиентом имитирующим пятно света. Все это делается в дизайнере, за исключением отрисовки контрола в битмап т.к. TBushGrab, являющаяся одним из вариантов использования кисти, корректно не работает.

 

Исходник и скомпилированный пример можно скачать тут.

пятница, сентября 28, 2012

Delphi XE3.FireMonkey: Фиксим рваную анимацию

О проблемах с анимацией в FireMonkey я уже неоднократно писал. Причина кроется в недостаточной точности используемого типа - Single. С переработкой FireMonkey на архитектуру сервисов, произошедшую в Delphi XE3, появилась возможность очень просто этот косяк пофиксить. В общем, фикс можно скачать отсюда.

 

p.s. Достаточно подключить модуль к проекту. Работает начиная с Delphi XE3. Будем надеяться, что с первым апдейтом этот фикс станет ненужен.

вторник, сентября 25, 2012

Delphi XE3.FireMonkey: куда ни кинь – всюду клин.

Это просто ужас какой-то – за что-бы ни взялся, ну просто все глючит :( После предыдущего подхода закончившегося серией QC-отчетов и серьезно охладившего пыл, сегодня решил еще поиграться с новым редактором стилей (о нем писать не буду – он ужасен. Даже элементарных действий по изменению Z-order для объектов нет, а Copy/Past умудряются глючить. Впрочем не удивительно, Крюков же говорил, что ему удобнее с текстовым представлением работать, видимо и нам нефиг расслабляться) и сделать небольшое т.н. gloat-logo наподобие такого:

firebird

Для этого я векторизовал в Inkscape изображение шлема с картинки для TLiveTile. Получилось довольно не плохо:

delphi_logo

А вот так это отображается посредством TPath:

dxe3

Для сравнения скриншот Delphi XE2 Update 4:

dxe2

В общем, пользоваться этим нельзя.

 

QC#109005

Update: 26.09.2012 11:07

Пришлось залить на QC два готовых проекта демонстрирующих баги компонента. Кстати, имеет значение каким образом будет заполняться путь: через инспектор объектов или через редактор компонента. Глючат оба варианта. Кому интересно скачайте приложенные проекты.

воскресенье, сентября 09, 2012

Delphi XE3. Очередной сырой релиз Firemonkey.

Багу с анимацией не поправили, она как была рваная так таковой и осталась. Причины они, похоже, поняли. Типу Single, используемому для счетчика тиков таймера (и кому в голову такая идея пришла, для счетчика использовать нецелочисленный тип) не хватает точности если у системы большой аптайм. В IFMXTimerService.GetTick они заменили его на Extended, а вот в реализации класса TAnithread забыли.

ani_bug

QC#108614

 

TreeView стало сильно нагружать CPU. Для дерева с одной тысячей элементов загрузка доходит до 100% в состоянии покоя. Мне не понятно, они там вообще ничего не тестируют что-ли?

treeview_bug

QC#108615

 

Еще вылез косяк с пропадаением/мерцанием шейдерной тени в 3D. Но тут без репорта, ибо надоело.

 

Регрессию с отсутствием сглаживания на XP тоже не пофиксили, а ведь она висит с выхода XE2 Update 4 Hotfix 1.

 

Update: 20:17 09.09.2012

Налетел еще на один косяк с тенью. Тень привязанная к объекту, который в свою очередь привязан якорями к своему контейнеру, не обновляется при изменении его размеров, а, похоже, просто подгоняется под размер.

shadow_bug

QC#108620

 

Update: 23:46 12.09.2012

Удалось воспроизвести еще один косяк с эффектом тени. На TForm3D размещен прозрачный TLayer3D с объектом внутри. Объекту назначен эффект тени. Тень пропадает, когда активизируется другой шейдерный эффект (это, кстати, регрессия, на XE2 такого небыло):

shadow_bug2

QC#108719

четверг, августа 30, 2012

Lazarus 1.0. Релиз.

Свершилось. Lazarus 1.0 релизнулся. Поздравляем команду работавшую над этой замечательной средой со столь важной вехой. Буду постепенно адаптировать свои наработки под FreePascal, чтоб в перспективе полностью слезть с Delphi. Абракадабра, похоже, совсем берега потеряла.