kryslt / KControls

Free components for Delphi and Lazarus, this is the main repository maintained by the original author.
BSD 3-Clause Clear License
59 stars 32 forks source link

Multilevel Bullets #35

Closed davidbannon closed 1 year ago

davidbannon commented 3 years ago

Hi TK. I am getting some requests from my end users to be able to do multilevel bullet points in a kmemo. As I understand it, having done some experimenting with the paragraph numbering, each indentation level must use a different TKMemoParaNumbering. And my end users don't like the use of numbers or letters.

TKMemoParaNumbering = (pnuNone, pnuBullets, pnuArabic, pnuLetterLo, pnuLetterHi, pnuRomanLo, pnuRomanHi);

Only pnuBullets is non-sequential. Seems I have two choices -

I guess what would really work is if we had a couple more items in TKMemoParaNumbering, pnuSmallBullet and pnuTinyBullet ?

Davo

kryslt commented 3 years ago

Hello David, it seems there was some preparation for this, but it was not finished. I've added some other bullet styles. Please note this was a quick fix. Also the built in kmemo editor and the numbering dialog has plenty of bugs here - setup not easy, etc. But as you can see its usable on component level. obrazek. I keep this open if more work is needed...

davidbannon commented 3 years ago

Oh, thats brilliant TK, I will setup some tests and get back to you !

Davo

davidbannon commented 3 years ago

Right, that seems to work fine for me. I have not tried it yet in tomboy-ng but it works well in my test rig, as below. The two current users seem to think that having three bullet levels is OK but I suspect there is a longing for more. So, I will present as having three levels of bullets, if you go past that you get the sequential markers instead. I don't offer a dialog to select bullet levels, users press ALT->{left|right}Arrow to increase or decrease bullet level so its easy to see you have gone beyond the 'bullet' scale.

Thanks Tomas, both I and my end users are very grateful. Once I have pushed this to my real app and tested, I'll ask the Online Package Maintainer to update his version.

bullets

Davo

davidbannon commented 3 years ago

Actually TK, wondering if you could add one more bullet ? Four levels seems enough and I just used pnuLetterLo as the forth but find that the sequence of the letters does not restart when there is a break in the bullets, as shown below. Now, I can, in code, restart that sequence but I would rather not given that this code is being called with every keypress (near bullet content) and, as we don't really want the sequence anyway, one more fixed bullet would be a lot neater.

I would suggest char $25B9 small white triangle. bullets

Davo

kryslt commented 3 years ago

Ok I made it, sorry for the delay.

I've chosen $25CB (pnuCircleBullet) because of better font support on old Win7. I'm not sure if this approach is correct, though. It seems to me now that better way is to have only pnuBullet enumerator and a new BulletCharacter property which would allow to specify the bullet character arbitrarily. Probably MS Word etc. do it this way. Will think of it later. I will keep the existing pnu... enumerators for backward compatibility for sure.

Please note the built in kmemo editor and the numbering dialog again does not work properly - you cannot set numbering font. However, on component level it is possible to change TKMemoListLevel.NumberingFont to select a font where those characters are actually supported. A test is needed on every supported operating system with given font...

I keep this still open if more work is needed...

davidbannon commented 3 years ago

Yes, I agree, a more flexible arrangement would be to have, maybe, four or five ( perhaps a very few more) bullet 'slots'. Like what we have now were we can change the indent of those slots and the change applies to every bullet in that KMemo, we should be able to set the Bullet character.

Perhaps you will need to introduce a new enumerated type that describes the Slots themselves rather than its characteristics (ie pnuArrowBullet), maybe xxxBulletOne..xxBulletSix.

That way, in my code, I can initialize the Bullets when KMemo starts and then, set a para to eg xxBulletFour knowing it will come out as initially setup.

For example, my testers are finding the ArrowBullet too obtrusive, that should not be your problem, it should be mine.

Davo

davidbannon commented 3 years ago

Attached is an image of a kmemo showing the bullet characters used in my current pull request.

Davo bullets

kryslt commented 3 years ago

Davo, I've merged your pull request but I have problem with the new bullets on Win 10. Eg. the very basic Arial font does not support any of the new characters except 0x2022 (basic round bullet which seems to be supported everywhere). I've checked in Windows character map. Did you test everywhere, Win, MAC? Also, the round bullet 0x2022 should be imo kept first. If there is no suitable match we must fix on specific cross platform font for bullets or maybe take them from font awesome or similar. EDIT: Or maybe the easiest thing will be to draw them using drawing primitives because I am not sure if it is possible to add font awesome or similar font as usable resource for the app in cross platform way (without the need to install the font in the system).

davidbannon commented 3 years ago

Wow, I don't understand that at all. I tested on Win 10 and an early Windows, worked perfectly on both. I wonder if its a locale issue ? Different underlying font may be selected depending on where you live ? I don't use the Windows 10 for anything other than testing like this so I have not added anything non standard. I'll make up a basic test app and try it on some other win10 installs I can find.

Yes, I did also test on Mac but only mac I have access to is an aging Powerbook running sierra so, now, I don't feel so confident. Of the people wanting these extra bullets, only one was a windows user from memory, no complaints from that user either...

Davo

kryslt commented 3 years ago

Well, it depends on the font. Maybe the cause is the Czech localization of Windows I use. Only some installed fonts in my system show all these bullet characters correctly, but not many! I assume this must be your case as well? We must use characters that will show up correctly everywhere, or select a specific numbering font, or draw the bullets using drawing primitives. Which font did you test and is safe to use across platforms? Maybe just assigning its name as NumberingFont in case of bullets will do the job.

davidbannon commented 3 years ago

Hmm, I am away from home at present, returning tomorrow, so I don't have access to any Windows machines (or Mac) right now. My Window install will be whatever the default one is and maybe that only applies here in Australia.

I absolutely agree that the bullets must work "out of the box" for the end user. I have had two beta tests out there for awhile now, maybe 60 windows downloads and no complaints yet. I make it plain its risky so users only download if they really want one of the new features so at least some of them must be multilevel bullet users. Perhaps.

I guess the sensible thing is to see what fonts are available on my Windows installs and I'll test them, one by one as you have done. That will at least tell us if if its a "font selection" issue or more systemic problem. Trouble is I really know very little about Windows, having stopped using it back with Windows 2000. And even back then it was just a terminal to reach the big machines off in the server room.

So, I am fairly new to Application Programming, its only Lazarus's ability to multi-platform that saves me !

If you don't mind me discussing this on the Lazarus Forum, I'll make a test app and appeal to the Windows users there ?

Davo

davidbannon commented 3 years ago

OK, I have tested on three Win10 and one Windows Vista (!) - same result on each one. And each one is using "Segoe UI" as the default font.

Here is my test code, I am guessing no point in sending you my Lazarus project, I assume you use Delphi ? Anyway, its dead simple, KControls not involved in any way, here is the important bit -

const
  { These are Bullet Characters. }
  cTriangleBullet : widechar = #$2023;
  cRoundBullet    : widechar = #$2022;
  cArrowTwoBullet : widechar = #$21A6;               // https://en.wikipedia.org/wiki/Arrows_(Unicode_block)
  cArrowOneBullet : widechar = #$21A3;               // https://en.wikipedia.org/wiki/Arrows_(Unicode_block)
  cCircleBullet   : widechar = #$2218;               // https://en.wikipedia.org/wiki/Mathematical_Operators_(Unicode_block)

procedure TForm1.FormCreate(Sender: TObject);
begin
    memo1.clear;
    memo1.append(string(cTriangleBullet) +' Right pointing triangle #$2023');
    memo1.append(string(cRoundBullet)    +' Round black circle #$2022');
    memo1.append(string(cCircleBullet)   +' Round white circle#$2218');
    memo1.append(string(cArrowTwoBullet) +' Arrow #$21A6');
    memo1.append(string(cArrowOneBullet) +' Another Arrow #$21A3');
    memo1.Append('');
    memo1.append('Current Font is ' + GetFontData(Self.Font.Handle).Name);
end;

So, number one question, do you have "Segoe UI" as the default font ?

Number Two Question : Should we be considering a model that uses the same symbol for all bullet levels ?

Davo

kryslt commented 3 years ago

Answer first question: I have "Segoe UI" font but it does NOT provide these characters. But I have "Segoe UI Symbol" which does provide them! Answer second question: No, there should be IMO more symbols like those you've introduced.

Of course best solution would be to use a well defined font that is available on EACH system. Like font awesome that is often used in web develoment. But that is not the case. Linux has different font names (I use virtual Ubuntu 20 now), Mac as well (I use virtual Catalina now). Because of the difficulties with various fonts I see only one solution - draw them on my own. Will see what can be done.

davidbannon commented 3 years ago

Yes, preselecting the font would be a bad way to go IMHO. If we select a particular font, and, as noted, it will have to be OS dependent, then we are overriding the user's choice. And, don't forget, most Linux distributions choose their own default font and LCL (and I assume Delphi) does not raise any error if you request a font that is not available.

My app lets users select the font they want to use, if a user chooses a font that does not display every thing they need, thats their business but if we select a non standard one at startup, then we are are overstepping.

By draw them on (your) own, you mean present them as images ? I would be worried about that slowing down the rendering, at present, I do not support inline images at all (although a couple of users have requested it). For me, speed may be more important that having different characters for each bullet level.

Davo

kryslt commented 3 years ago

I see. I've tested possibilities shortly. Drawing bullets by using drawing primitives is bad, since there is no native support for anti-aliasing by VCL/LCL and they look ugly without that. Using images/bitmaps is also bad, since the images would need to be big enough and their resampling and rendering would be very slow (you mentioned that). Using one system font is also bad because there is no such font available accross various systems. Using custom font like font awesome is also bad because there is no native support to add custom font by VCL/LCL without the need to install it in the system (there are some packages like EasyLazFreeType but we cannot rely on them).

We must provide reasonable solution, there must not be unknown character glyph instead of the bullet by default. But there are almost no options.

The only option i see is to add global property eg. TKMemo.BulletFontName: string. This has different name for each OS then. For Windows 'Segoe UI Symbol' seems to be a good choice because it is supported on Win7 through Win10 (don't know about Vista or older but they are almost not used anymore). For Linuxes it will be empty string since there is no assumption (too many distributions and versions). For MAC it seems to be 'Arial' but I'll check this more in detail. In case TKMemo.BulletFontName is set to empty string the control will behave as now.

kryslt commented 3 years ago

More info. It seems some typical Windows only mess plays a role here. Eg. the Tahoma font does not expose character 0x21A3 (not shown in Windows char map or even in FontForge) but ExtTextOut draws it! Another font, eg. Arial, does not expose it and ExtTextOut does not draw it, as assumed. What is going on inside Windows API? Either way, the safest choice for Windows will be a font where those characters show up in the char map and draw correctly. Will check for Windows versions I use, it means 7 and 10.

davidbannon commented 3 years ago

Hmm, "Segoe UI Symbol" ? Does that same font also display the normal text, ASCII and extended, characters ? Or are you planning to use the bullet char from "Segoe UI Symbol" and the rest of the text something else ?

If you just switch all content to "Segoe UI Symbol" then its not really a KControls issue, you leave it up to next layer above to do that. Its really my app that chooses to use "Segoe UI Symbol" because I will be using multilevel bullets OR not to worry about it because its not important in my particular use of KControls.

And, mind if I raise it again, same image for all levels ? Or a limited number ? Github uses only three symbols for, apparently, unlimited levels. It does one, then another, then a third that is used for all subsequent levels, Honestly, I think one symbol would be OK if its an alternative to an overly complicated or fragile solution.

Davo

kryslt commented 3 years ago

That font will only apply for bullet characters, nothing else. Plus there will be option to disable it so that paragraph font will be used for bullets as is the case now. I also consider to keep only pnuBullet and introduce new BulletCharacter property for each numbering list. Like I mentioned before. This way we can modify both the bullet font and bullet characters. No need to limit number of available bullets then because everything will be fully configurable.

davidbannon commented 1 year ago

This is well and truly solved, I thank you ! (and my users thank me !)

Davo