News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests
NB: Posting URL's See here: Posted URL Change

Main Menu

TextView

Started by Biterider, May 07, 2020, 06:34:09 PM

Previous topic - Next topic

Biterider

Hi
While developing an application, I had to display formatted text and used the RichEdit control for this purpose. I found it to be an overkill and DLL nightmare, so I decided to look for alternatives.

I analysed the amazing and well known works of:
and decided to go a somewhat different way. Instead of using HTML, I created my own markup definition. The goal was that it should be simple, MASM, keyboard and printf friendly.

I experimented with different syntaxes and finally found two sets of tags: styles and commands.
A style defines how text is displayed (font, size, color, background, etc.), while commands trigger immediate actions (tab stops, line breaks, paragraphs, etc.). As with the previous implementations, styles are managed in a stack, so that previous sytles can be reused as soon as the newer style is popped off.
TextView is created in the form of a control to facilitate the implementation of active areas. These areas are sensitive to user interactions such as hyperlinks, buttons, tooltips, etc.
Here is a summary of the currently implemented markups:

Styles:
APP   Application notification
SUB   Subscript
SUP   Superscript
BOLD   Bold
FONT   Set font face
INFO   Information callback
ALIGN   Set alignment
COLOR   Set background color
HEIGHT   Set font height
INDENT   Set indentation
ITALIC   Italic
BGCOLOR   Set background color
STRIKEOUT   Strikeout
UNDERLINE   Underline


Commands:
TAB   Performs a tabstop
DRAW   Parent draw
PARA   Start a new paragraph
TABC   Define a "tabstop center"
TABL   Define a "Tabstop left"
TABR   Define a "Tabstop right"
BREAK   Perform a line break
COVER   Parent drawing covering all previous actions
SIZE.X   Set draw area width
SIZE.Y   Set draw area height
TABCLR   Reset all tabstops
PADDING   All paddings
PADDING.TOP   Set pop padding
PADDING.LEFT   Set left padding
PADDING.RIGHT   Set right padding
PADDING.BOTTOM   Set bottom padding


The drawing process takes place in two steps. The first step is to parse the markup string using a state machine and generate all the GDI style resources (fonts, brushes, etc.). This output is used in the second step to execute the commands and render the individual drawing units.

There are three parent callbacks implemented. APP, INFO and DRAWING. The APP callback informs the parent window about mouse activities in the active areas. INFO callbacks request information to display tool tips, and finally DRAW callbacks request drawing operations. This last type of callback can be executed during the rendering process or at the end, covering all previous rendering tasks.

I attach two executables showing the TextView replacement of the standard about dialog (check the active areas - circled i) and a demo showing the tabbing, indenting and sub- and super-scripting capabilities.

Here ist the source of the markup string of this last Demo:

CStr szMarkupText,    "{Padding 20}", \
                      "{TabC 130}{TabR 210}", \
                      "[Indent 10, H +2, Bold, Underline]", \
                        "Description{Tab}Qty{TAB}Price{P}", \
                      "[~]", \
                      "[Indent 15, Color #4F4FFF, H +2, Italic]", \
                          "{#2022} Item[Sub]1[~]{Tab}2{Tab}2.35[Sup]*[~]{B}", \
                          "{#2022} Item[Sub]2[~]{Tab}200.0{Tab}20.00[Sup]**[~]{B}", \
                          "{#2022} Item[Sub]3[~]{Tab}0.1{Tab}0.23{B}{P}", \
                      "[~]", \
                      "{TabClr}{TabC 80}{TabL 95}", \
                      "[Indent 30, Color #4F4F4F]", \
                        "Note:{Tab}*{Tab}Volume discount{B}", \
                        "{Tab}**{Tab}Regular discount", \
                      "[~]", \


The source code will be released soon in the next ObjAsm update.

Have fun,  :biggrin:

Biterider

jj2007

Nice :thumbsup: When does the Rtf-TV converter come?

Biterider

Hi JJ
No plan for such a converter, but for a WYSIWYG editor, like the one of Hans Dietrich.
In that way, you see immediately the markup effect while typing it.

Biterider

HSE

Hi Biterider!

Quote from: Biterider on May 07, 2020, 06:34:09 PM
While developing an application, I had to display formatted text and used the RichEdit control for this purpose. I found it to be an overkill and DLL nightmare, so I decided to look for alternatives.

Fantastic idea!

We have seen how You use formatted text. And so far TextViewer look pretty good for that. I think to add paragraph center option could improve the control a lot. Of course I'm thinking how I can use the control, but here table example only use left half of the window, and don't look so impressive. About example, on contrary, is in right and bottom limits.

Regards. HSE
Equations in Assembly: SmplMath

Biterider

Hi HSE
This is the markup string for the About Dialog

"{Padding 20}", \
"[Height 11]", \
  "{Cover 0}", \
  "[Indent 150, Align 'LEFT']", \
    "[Height +3, Bold]&ABOUT_TEXT{B}[~]", \
    "[Italic]Version &VER_PRODUCTVERSION_STR{P}[~]", \
    "[Color #3F3F3F]", \
      "Designed with ObjAsm{B}", \
      "© &COPYRIGHT{P}", \
      "[Color #5F4FFF]", \
        @CatStr(<!">, %BUILD_DATE_STR, \
                <  -  Build: >, %BUILD_NUMBER, <->, %ASSEMBLER, <->, \
                %TARGET_MODE_STR, <->, %TARGET_BITNESS, <    !">), \
        "[Info ", @CatStr(<!">, %INFO_BUILD, <!">), ", Font 'Webdings', Height +1]{#69}[~]", \
      "[~]{B}{B}", \
    "[~]", \
  "[~]", \
  "[Indent 0, Align 'CENTER']", \
    "[Font 'Webdings', Color #FF5F5F, Height +7]{#7E}[~]", \
    "  Visit us at  ", \
    "[App ", @CatStr(<!">, %APP_VISIT, <!">), ", Color #0000FF, U]www.objasm.x10host.com[~]{B}", \
    "[Font 'Wingdings', Color #408090, Height +1]{#2A}[~]", \
    "   Email us to  ", \
    "[App ", @CatStr(<!">, %APP_EMAIL, <!">), ", Color #0000FF, U]objasm@gmx.net[~]{P}", \
    "[App ", @CatStr(<!">, %APP_CHECK, <!">), ", Color #0000FF, U]Check for updates[~]", \
    "[Info ", @CatStr(<!">, %INFO_UPDATE, <!">), ", Font 'Webdings', H +1, Color #5F5FFF]  {#69}[~]", \
  "[~]", \
"[~]"


I used @CatStr(...) to embed some constants I used on the parent window

APP_VISIT     equ   0
APP_EMAIL     equ   1
APP_CHECK     equ   2
INFO_BUILD    equ   0
INFO_UPDATE   equ   1


The implementation is pretty straight forward

Method Application.OnNotify, uses xdi xsi, wParam:WPARAM, lParam:LPARAM
  local Img:$Obj(Image), DstRect:RECT

  SetObject xsi
  mov xax, wParam
  .if xax == VIEW_CTRL_ID
    mov xdi, lParam
    .if [xdi].NMHDR.code == TVNMC_APP_MOUSEUP
      .if [xdi].TVNM_APP.dID == APP_VISIT
        invoke ShellExecute, [xsi].hWnd, $OfsCStr("open"), \
                             $OfsCStr("http:/objasm.x10host.com/index.htm"), \
                             NULL, NULL, SW_SHOW
      .elseif [xdi].TVNM_APP.dID == APP_EMAIL
        invoke ShellExecute, [xsi].hWnd, $OfsCStr("open"), \
                             $OfsCStr("mailto:objasm@gmx.net"), \
                             NULL, NULL, SW_SHOW
      .elseif [xdi].TVNM_APP.dID == APP_CHECK
        invoke MessageBox, [xsi].hWnd, $OfsCStr("No update available."), \
                                       $OfsCStr("Information"), \
                                       MB_ICONINFORMATION or MB_OK
      .endif

    .elseif [xdi].NMHDR.code == TVNMC_INFO
      .if [xdi].TVNM_INFO.dID == INFO_BUILD
        c2m [xdi].TVNM_INFO.pText, offset szBuildInfo, xax

      .elseif [xdi].TVNM_INFO.dID == INFO_UPDATE
        c2m [xdi].TVNM_INFO.pText, offset szUpdateInfo, xax
      .endif

    .elseif [xdi].NMHDR.code == TVNMC_DRAW
      .if [xdi].TVNM_DRAW.dID == 0
        New Img::Image
        OCall Img::Image.Init, xsi
        OCall Img::Image.%LoadFromRes, $OfsCStr("OA")
        mov DstRect.left, 35
        mov DstRect.top, 35
        mov DstRect.right, 100
        mov DstRect.bottom, 100
        OCall Img::Image.AlphaDraw, [xdi].TVNM_DRAW.hDC, 255, addr DstRect
        OCall Img::Image.Done
      .endif
    .endif
  .endif
MethodEnd


Biterider

HSE

Ok  :thumbsup:

We have to test that  :biggrin:

Thanks
Equations in Assembly: SmplMath

Biterider

Hi
A little bit of color makes it look a lot better.  :biggrin:
This demo shows text alignment to the left/center/right using tabs, subscript and superscript, indentation, different font styles and sizes, colors and PNG shrinking and alphablending.

Biterider

daydreamer

so it would be possible to split first part parsing to a "compiler" part and the program you release have that in smaller "compiled" data
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

Biterider

Hi
Yes, technically possible. The other way is to use the buildin streaming capabilities to save the content of the collections into a stream and store these data afterward into the resource section. A bit more work has to be done, but it is definitively possible.

Biterider

daydreamer

Quote from: Biterider on May 31, 2020, 01:25:48 AM
Hi
Yes, technically possible. The other way is to use the buildin streaming capabilities to save the content of the collections into a stream and store these data afterward into the resource section. A bit more work has to be done, but it is definitively possible.

Biterider
sounds good
I have recently worked with HTML/scripting and learned some things
maybe accompany it later with a event handler proc's that or several procs that does interactive things similar that scripts in HTML does?
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

Biterider

Hi daydreamer
Similar behavior has already been implemented. If you look closely, you'll see a collection called ActiveTVAreas. It contains the "hot" areas that can interact with the user.
In the current implementation, when the mouse interacts with the "hot" areas, information is sent or requested from the parent window using notifications. This is how the hyperlink and tooltip work.
I can see many other ways to use it too, e.g. to create a button or more complex controls.
Still, I didn't go any further because I thought it would be a better approach to use the traditional controls to keep functionality and complexity where they belong.

Biterider

Biterider

Hi
I have completed the last development step of this control. It now comes very close to the amazing work of fearless :cool:
http://masm32.com/board/index.php?topic=7372.0

I added more functionality, word wrapping, text boxing, scrollbars and mouse wheel support and cleaned up the code.

Biterider

Biterider

#12
Hi
Today I want to show you the new TextView. It's a completely redesigned version where I've implemented what I learned from the previous code. In addition to heavy refactoring, I added some very useful features.

The aim of TextView is to draw reach-formatted text easily and fully automatically, taking over the management of all resources required for the drawing process. It uses a markup text to instruct what to do and set the styles for the drawn text. This code is completely GDI based. This allows you to render on any device that supports Windows, even without GPU support.

This version was developed for the usual 32/64 and ANSI/WIDE targets. Internally, however, TextView works with WIDE strings, enabling the rendering of all characters that Windows can draw (BMP). If you compile for ANSI string target or you can't enter Unicode characters in your editor, you can enter them using dedicated markups. For example, this situation may occur when you want to list bullets.

Zooming is one of the added new features. It is vector-based and allows you to draw scaled text without any loss of accuracy.
To enable use on mobile devices, gesture support for panning, over-panning and zooming is also supported beyond the legacy windows implementation.
All the rendering options are global and can now be set in the markup string too.

With the "Automatic line break" option, you can adapt automatically the drawing to different client sizes. A nice example are message-boxes with large texts. They adapt to a dynamic layout or display a vertical scrollbar to see the rendered text on a smaller view.

Supported functions are also styles, short markups, tooltips, active areas, adjustable tabs, line breaks, paragraphs, indentations with hanging, custom padding on all edges, text and graphic callbacks, text boxes, alignment, etc.

In the background, the rendering process uses double buffering, which results in flicker-free visualization. Due to the use of look-up tables, the analysis, pre-calculation and drawing process is very fast. On my system, the representation of a markup string of about 100 commands was parsed and precomputed in 25 microseconds and rendered in 5 milliseconds.

TextView is lightweight. It has a code footprint of 30 KB in 64 bit.

As usual, it is licence free and open source.

Attached are 2 revised examples. One shows the rendering features, active areas and tooltips, while the second shows zooming and gesture handling.
The documentation is included in the source code file on GitHub.

Have fun.  :cool:

Biterider

TouEnMasm


creating a control edit is a good idea.
Nightmare come with Msftedit , need to be used only in unicode or to have big problems.
If TextView can do the same thing than a richedit,that will be perfect.
Fa is a musical note to play with CL

fearless

Excellent stuff. Its looking great.