Author Topic: TextView  (Read 481 times)

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 525
  • ObjAsm Developer
    • ObjAsm
TextView
« on: May 07, 2020, 06:34:09 PM »
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:

Code: [Select]
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

  • Member
  • *****
  • Posts: 10319
  • Assembler is fun ;-)
    • MasmBasic
Re: TextView
« Reply #1 on: May 08, 2020, 12:25:24 AM »
Nice :thumbsup: When does the Rtf-TV converter come?

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 525
  • ObjAsm Developer
    • ObjAsm
Re: TextView
« Reply #2 on: May 08, 2020, 01:50:46 AM »
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

  • Member
  • *****
  • Posts: 1315
  • <AMD>< 7-32>
Re: TextView
« Reply #3 on: May 09, 2020, 12:23:10 AM »
Hi Biterider!

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

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 525
  • ObjAsm Developer
    • ObjAsm
Re: TextView
« Reply #4 on: May 09, 2020, 02:46:19 AM »
Hi HSE
This is the markup string for the About Dialog

Code: [Select]
"{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

Code: [Select]
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

Code: [Select]
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

  • Member
  • *****
  • Posts: 1315
  • <AMD>< 7-32>
Re: TextView
« Reply #5 on: May 09, 2020, 03:24:15 AM »
Ok  :thumbsup:

We have to test that  :biggrin:

Thanks

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 525
  • ObjAsm Developer
    • ObjAsm
Re: TextView
« Reply #6 on: May 13, 2020, 04:01:27 AM »
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

  • Member
  • *****
  • Posts: 1261
  • building nextdoor
Re: TextView
« Reply #7 on: May 30, 2020, 11:37:44 PM »
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
Quote from Flashdance
Nick  :  When you give up your dream, you die
*wears a flameproof asbestos suit*
Gone serverside programming p:  :D
I love assembly,because its legal to write
princess:lea eax,luke
:)

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 525
  • ObjAsm Developer
    • ObjAsm
Re: TextView
« Reply #8 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

daydreamer

  • Member
  • *****
  • Posts: 1261
  • building nextdoor
Re: TextView
« Reply #9 on: May 31, 2020, 08:10:14 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?
Quote from Flashdance
Nick  :  When you give up your dream, you die
*wears a flameproof asbestos suit*
Gone serverside programming p:  :D
I love assembly,because its legal to write
princess:lea eax,luke
:)

Biterider

  • Moderator
  • Member
  • *****
  • Posts: 525
  • ObjAsm Developer
    • ObjAsm
Re: TextView
« Reply #10 on: May 31, 2020, 02:59:58 PM »
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

  • Moderator
  • Member
  • *****
  • Posts: 525
  • ObjAsm Developer
    • ObjAsm
Re: TextView
« Reply #11 on: June 15, 2020, 06:52:29 AM »
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