What should we do with textareas and textfields?

Use bog-standard components. We don't need transparency, bold/italic/underline, colour, clickable links or graphical hints in th
60% (3 votes)
Make better components. We don't need support for bizarre languages, nor cut-n-paste.
20% (1 vote)
Do both! We don't need fast development.
20% (1 vote)
Do neither. I have a better idea...
0% (0 votes)
Total votes: 5

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Day More: A choice needs to be made.

I'd appreciate people's thoughts on this one.

For the client to do everything I want it to with text components, I need to create my own text components from scratch. This means TOTALLY from scratch - positioning the text on the lines, wrapping it, moving the cursor, selecting, highlightig, etc, will need to be competely done over. None of this can be taken from a preexisting component

If I do this, then we will lose some of those things we already have:
1) Ability to use an IME to type in Japanese or other languages.
2) Ability to use the system clipboard to copy to/from Thud windows (copying between thud windows would still be feasible).
3) Multiple directional text.

We will gain advantages though:
1) transparent and non-rectangular textareas,
2) clickable email addresses and URLs,
3) multiple font faces, colours and styles in the same component (eg, italics, etc).
4) images and icons within text components (emoticons, rank icons, etc).

Whatever happens, I need to implement at least part of this for labels, for the skinners. I want to create transparent lightweight components that will allow some very limited HTML tags (a, img, b, i, p, br with limited attributes like color, align, style) so that the skinners can easily make a layout with arbitrary clickable buttons and text.

This could be a good time to fork the client in two - an international, compatible, bland one, that ignores parts of the spec that it can't understand, and a pretty one that implements more of the spec. But that means more work for me, a higher likelihood of bugs in one fork or the other, and hence slower development. It also means two different downloads, leading to confusion for users.

Another way to split it is to could make using pretty textareas and textfields an option, configurable under the settings menu, and have both in the same client. Slightly larger download size, but more coherent, perhaps.


Hrm. i found a good set of J1.1 lightweight rich text components, trouble is, they add more than 630k to the download. That'd more than triple the download size, taking it over a meg, just to get us pretty text.

So I need to write my own, very customised solution. Just need tabpanel, label, list, textarea-with-input, and textfield.

Need to be able to deal with all the usual hotkeys that people expect in these components, too:

[edit: I was thinking too much AWTy: textarea doesn't need to be editable, and needs to be controllable from the attached textfield)

Text Labels:
Leftclick: activate link
Doubleclick: activate link
Shift + F10 or Rightclick or AppsKey: Context menu showing link target

Text Area (not keyboard focusable, display only):
LeftClick: activate link
Doubleclick: select word, activate link
Leftclick-drag: select text and copy to clipboard.
Shift + F10 or AppsKey + mouseover or RightClick: Display context menu for link target, etc.

Text Field (input):
Up: previous line in input history
Down: next line in input history
Left: Cursor left
Right: Cursor right
Home: cursor to beginning of line
End: cursor to end of line
Tab: Complete a nickname
Enter: submit text.
Ins: change to insert mode
Del: delete to the right of the cursor, or selected text
Ctrl + Del: Delete upto/including the next rightmost whitespace or punct.
Backspace: delete to the left of the cursor, or selected text
Ctrl + Backspace: Delete upto/including the next leftmos ws or punct.
PgUp: scroll any attached display up one page
PgDn: scroll any attached display down one page
Ctrl + Up: Scroll any attached display up one line
Ctrl + Down: Scroll any attached display down one line
Leftclick: place cursor
Doubleclick: select word
Tripleclick: select all text
Leftclick-drag: select text.
Shift + F10 or AppsKey or RightClick: Display context menu for style, copy/paste, etc.
Ctrl + C or Ctrl + Insert: Copy.
Ctrl + X or Shift + Delete: Cut.
Ctrl + V or Shift + Insert: Paste/Move.
Ctrl + Z: Undo.
Ctrl + A: Select all.
Ctrl + Left: Move cursor to the beginning of previous word.
Ctrl + Right: Move cursor to the beginning of next word.
Ctrl + Home: Cursor to beginning of text.
Ctrl + End: Cursor to beginning of text.
Shift + Left: Highlight one character to the left.
Shift + Right: Highlight one character to the right.
Ctrl + Shift + Left: Highlight to beginning of previous word.
Ctrl + Shift + Right: Highlight to beginning of next word.
Ctrl + Shift + Home: Select to beginning of text.
Ctrl + Shift + End: Select to beginning of text.
Ctr + B: Format text in bold.
Ctr + I: Format text in italics.
Ctr + U: Format text as underlined.

Lists:
Leftclick: select item
Doubleclick: activate item
Home: Move cursor to top
End: Move cursor to bottom
(letter): cycle items beginning with that letter.

Tabs:
Leftclick: select tab
Ctrl + Tab: Cycle through tabs.
Ctrl + Shift + Tab: Cycle backwards through tabs.

General:
Ctrl + F or F3: Find (maybe?)
F1: Open help.
F11: Toggle full screen mode.
Alt or F10: Activate menu bar.
Alt + (Letter): Activate item corresponding to (Letter). (Letter) is the underlined letter on the item's name.
Tab: Forward one item.
Shift + Tab: Backward one item.
Space: Toggle items such as radio buttons or checkboxes.
Ctrl + L or F5: Refresh


Founding PatronLibrarianDruidThudmeister

My inclination would be to go for bland (option 2) for now, and then as and when you've got time think about jazzing it up. Unfortunately, life being as it is, I expect choosing the easy version would make it impossible to implement the interetesting version without completely rewriting major chunks of code.

On the subject of languages, various places seem to agree that the top ten are Mandarin, English, Hindi, Spanish, Russian, Arabic, Bengali, Portugese, Malay-Indonesian and French, with some differences over the order. Of those, only half use the latin character set, but which do we really expect to see huge numbers of users wanting? I wouldnt want to display my ignorance by guessing which countries Pratchett sells well in - perhaps it would be worth checking the IP addresses of visitors for a while (say a week) and getting rough figures from that.

Certainly I think forking the client wouldn't be a good idea. Firstly, as you say, it'd give you more headaches than you can shake a stick at and thus slow development. Also, it's very easy to confuse people who've just arrived, havent seen any of it before, and are a little shy because (unlike across most of the internet) they're actually going to interact with real people (and people they don't know into the bargain), so they're scared of getting things wrong & looking foolish.

Just my 2p worth
Mr Scrub


Mr Scrub wrote:

My inclination would be to go for bland (option 2) for now,

Yopu have to click the votey buttony thinguses or the vote won't get counted by the system Razz

Quote:

[...]top ten are Mandarin, English, Hindi, Spanish, Russian, Arabic, Bengali, Portugese, Malay-Indonesian and French[...]

Yup. Though, as well as the appeal to Pratchett audiences, there are also other aspects to take into consideration.

For example, if we want to get past the great firewall of China, we MUST support Chinese, since they non-Chinese-enabled games are blocked ad illegal.

And there's the question of where does pTerry hope to grow to in future? If he intends to target, say, the middle east, then we need to support that.

Also, this applet is intended to show the minimum level of functionality expected from any future Thud client, so that people can most easily port it to other languages.


Founding PatronLibrarianDruidThudmeister
Dewi Morgan wrote:

Yopu have to click the votey buttony thinguses or the vote won't get counted by the system Razz

Mummy - the nasty Druid's picking on me Wink

The point was that it wasn't a definite "option 2" vote - only a kind of temporary idea. And anyway, on reflection (and looking at the options again), it wasn't option 2 I meant anyway, but option 1 - otherwise my statement doesnt really make a lot of sense: option 2 is the interesting but problematic one, and I called it the bland one (bear of very little brain).

Have now voted option 1, just to get you off my back Razz

Mr Scrub


Coding textareas is un, though. And there's lots more to take into account than you'd think at first light.

Stuff like this is a problem when you're creating your own text compoent. Now, odds are I won't bother fixing this, partly because the fix would be worse than the problem. But it's something to be considered, at least.

Java 1.1 (and later versions for all I know) prettymuch only gives inormation about fonts as their outer graphical bounding boxes. Which is great, and exactly what you need, if you're placing the text within, say, a frame.

But if you're butting two pieces of text together in a ligature, especially in large italic fonts, then they need to butt together far closer than their bounding boxes would allow.

Another issue is wrapping. Now, the algorithm for wrapping text is easy enough, you find the last whitespace before the end of the available space, otherwise the last hyphen, otherwise the last punctuation, otherwise the last character.

What if there is only one character, font size 1000? Scrollbars? What if most of the page is size 12, and only the last character is size 1000? Then the whole page has scrollbars? What if it's a large image? [My solution to this: Never allow horizontal scrollbars in display textareas. If a component (image or character) is too large to fit horizontally, scale it down].

What about spaces? If I wrap at the end of the line, what should I do about multiple spaces?

Original text (spaces shown as dots):
 A.line.with.many.......spaces

Place that within a 20-character wrapping.

|<-Wrapping Width->|
 A.line.with.many..[*]   - Newfangled, "invisible spaces"
 spaces

|<-Wrapping Width->|
 A.line.with.many..      - Old fashioned, "character based"
 .....spaces

|<-Wrapping Width->|
 A.line.with.many.         - Possibly more intuitive?
 ......spaces

Thunderbird uses the first, newfangled method, silently "hiding" all the spaces at the end of the line. You could stick a thousand spaces in there, and you wouldn't see them until you tried to cursor off the end of the line, and found you had to hit your right arrow a thousand times before you get to the next line, even though your cursor will never appear to move for the first 999 keypresses. I eel this is a conclusive argument against this method.

The second, character based way SEEMS more intuitive, and it's the one I'll be using, but is it the best? It's very very easy to code for.

However, picture what happens if you have a line like so:

Original text (spaces shown as dots):
 A.line.with.many.spaces

Place that within a 20-character wrapping.

|<-Wrapping Width->|
A.line.with.many.
spaces

Now put the cursor at the beginning of the second line, and hit space:

|<-Wrapping Width->|
A.line.with.many..
spaces

The space has gone to the end of the first line instead! It's not until the fourth space you type that the word "spaces" starts to indent.

Because of that, it might be more intuitive to the user to put all extra spaces after the first onto the next line: at least the user can instantly and clearly see that there are extra spaces there, then, and won't accidentally create a file with way more extra spaces than he expected. If I was creating a proper windowing toolkit, I would probably do this. But I'm just making a game. So never mind.

Another thing to take into accout with wrapping is the weight of punctuation. Stylistically speaking, to a typesetter, the following is "less correct":

 This is some wrapped and justified text
 (as  you  can  see) that has been well-
 wrapped and properly justified.

than this:

 This is some wrapped and justified text
(as  you  can  see)  that  has been well-
 wrapped and properly justified.

In the latter, the opening bracket is outdented, overhanging the rest of the text. In justified text, the hyphen also overhangs, preferably by HALF a character-width. This "hanging punctuation" is a mark of a good typesetter.

This is because these punctuation marks have less "weight" than regular characters. This is described much better on mandership's blog (which I read religiously, though don't always agree with). It is interesting to note that his page, unlike the vast majority of the internet, has correctly hanging punctuation. Scales the window if you don't believe me - a cool though slightly clunky CSS trick.

And then there's the dificulty of knowing what text has been selected when someone clicks the mouse and drags it.

Not only is there the confusion about which area should be selected if tthe mouse starts out "unclaimed territory", there's also the question about text backgrounds. Should the colour of a text background be as high as the highest thing on the line (as with the selected area above) or only as high as the font claims to be (as with the yellow text background above)?

The above was rom OpenOffice, which uses the full line height for selections, but the font height for the text background. Personally, I'd use the full height for both. This would reduce the above confusion about selections, too: it would clearly select from both lines.

And I haven't even touched on right-to-left display, nor on the complexity of inputting a mix of LtR and RtL text on the same line (you get a thing called a "split cursor" - programming nightmare!)


Now you might have noticed that I've gone ahead with the whole "design new text components" thing, and this is becoming a development blog. Ho, hum.

Feel free to carry on voting Smile The development version of ThudGame is still in that state that'sthe virtual equivalent of lying in pieces on the mechanic's garage floor. It doesn't even compile, and the last time it compiled, it displayed something quite hideous. But I know where I'm going with this, honest.

Now, I have needed to decide what tags skinners can use (and typists can use) to make pretty labels and such.

My strategy for this is that all tags I allow will work until the next closing tag or \n character. This way, I can treat all "hard" lines astotally separate elements. And anyway, people can only send one line at a time, and if they don't close their tags it shouldn't afect what the next person types.

The tags I've selected so far are:

[b][i][u] - bold, italic, underline. Affect all text until the next closing tag or \n.

[url]uri-string description[/url] - the description is separated rom uri-string by whitespace. It is displayed as a clickable link to uri-string that the browser will open in a new page. If description is omitted then uri-string is shown as the description. Either way, the target URI should be shown as a tooltip if possible, otherwise should be available by rightclicking the link. Ideally logic should detect URIs with a URI in the description, and should mark it as a "potentially dangerous fake".

[img]uri-string description[/uri] - Description is ignored here, but in a web-based version could be used or alt-text. Displays an image which will be scaled to fit the width and height of the component if necessary.  The URI can be a keyword indicating a predefined graphic such as "user_portrait".

[size]number[/size] - font size in points. May be prefixed by + or - to change the size relatively. If invalid or none, the default size is used.

[face]name, name, name[/face] - comma delimited list of font face name preerences. First one found is used. If none are found (or none is given), default font is used.

[var]name[/var] - replaced by the text value of a variable such as player_name.

[fg]number or name[/fg]
[bg]number or name[/bg] - foreground and background colours. If invalid it will use the default colour. "transparent" is a valid colour

[center]text[/center] - center this text as best as possible. If it can't be fitted on the center of the current line, then it will be wrapped to the next line. The [right] tag also counts as a closing tag or this.

[right]text[/right] - Everything from the tag to the end of the line is aligned right. If there's a closing tag, everything after it is wrapped to the next line. "[right][/right]" can hence be used like \n to break the line, but without automatically closing other tags. The [center] tag also counts as a closing tag or this.

So as an example:

[size]+10[/size][b][var]user_name[/var][/b][center]VS[right][var]opponent_name

Would display as:
   Farrier    vs       Fred

or:
   Farrier    vs   Fred The
      Inordinately Evil Man
or:

   Farrier The Mighty
              vs   Fred The
      Inordinately Evil Man

In this case, displaying as three separate labels might be more sensible :)

All tags are lowercase and may not contain whitespace within the [] square braces. All closing tags are optional since they're closed by the end of line anyway. No tags have properties, which makes tokenising a ton easier.

Only some tags may contain tags within them (b, i, u, center, right, url, image).

Any thoughts on any other tags that might be useful, let me know! Smile


Text wrapping is a fun thing in itself.

With monospaced text, it's really easy:

Find the last word boundary before the Nth character.
   If there is one
     split there.
   Else,
     split on the Nth character.

With proportional fonts, it's trickier:

Split text into words.
lastGood = 0
Foreach WORD,
   If current width + wordwidth < availablewidth,
     lastGood = beginning of word.
     next WORD
   else if lastGood > 0
     Split at lastGood
   else
     split into letters.
     foreach LETTER
     If current width + letterwidth < availablewidth,
       lastGood = beginning of letter.
       next LETTER
     else
       Split at lastGood

But rich text? Now THAT gets interesting. Here's the best I can think of:

Create an empty array of Lines (Lines are single-line richtext strings, plus information about the maximum riser and descender for that line)

Replace all [var]iables in the body text with relevant values.
Repeat until no more var tags found, or max-repeats (since vars may contain var tags).

Split body text into strings at the linebreaks.
Foreach STRING
   set the font to the default font properties.
   locate the positions of each tag in the string.
   match each opening tag with a closing tag or the end of the string
   point lastGood pointer to the start of the string.
   set lineRiser and lineDescender to 0.
   WHILE the string is not empty
     set usedWidth = 0
     Foreach TAG,
       if it's an image tag,
         if imageHeight < maxLineHeight,
           scale the image to maxLineHeight.
         if imageWidth + usedWidth < availableWidth, 
           add width to usedWidth,
           set lastGood after the closing tag,
           next TAG.
         if it's the first segment (lastGood is the string start),
           scale the image,
           set lastGood after the closing tag.
         create substring from start of string to lastGood.
         Append closingtags for all open tags (optional)
         Add result to Lines array.
         String = substring from lastgood to end.
         Prepend opentags for to make current font (optional)
         Update tag offsets for new string.
         Next WHILE.
       else (it's a text tag),
         change the font by the properties from the tag.
         if there's no text until the next tag,
           next TAG.
         if largestOf(fontRiser, lineRiser)
         + largestOf(fontDescender, lineDescender) < maxLineHeight,
           scale the font to maxLineHeight.
         if stringWidth + usedWidth < availableWidth,
           add width to usedWidth,
           set lastGood before the next tag,
           next TAG.
         We're on the last tag of the line. Tokenise by words.
         Foreach WORD
           if wordWidth + usedWidth < availableWidth,
             add width to usedWidth,
             set lastGood before the next word,
             next WORD.
           Split word into letters.
           Foreach LETTER
             if letterWidth > availableWidth
               scale the font of the whole tag down to availableWidth.
           If it's NOT the first segment (lastGood isn't string start),
             create substring from start of string to lastGood.
             Append closingtags for all open tags (optional)
             Add result to Lines array.
             String = substring from lastgood to end.
             Prepend opentags for to make current font (optional)
             Update tag offsets for new string.
             next WHILE
           If it's the first segment (lastGood is the string start),
             Split word into letters.
             Foreach LETTER
               if letterWidth + usedWidth < availableWidth,
                 add width to usedWidth,
                 set lastGood before the next letter,
                 next LETTER.
               else
                 create substring from start of string to lastGood.
                 Append closingtags for all open tags (optional)
                 Add result to Lines array.
                 String = substring from lastgood to end.
                 Prepend opentags for to make current font (optional)
                 Update tag offsets for new string.
                 next WHILE

Loop through Lines array,
foreach Line,
  foreach image in the line, 
    set top of each image on the line to:
   (baseline-maxriser)+mod(imageHeight-maxRiser)

Note to self - don't read the BiDi algorithm. It makes your head hurt.

Some OTHER sucker can implement BiDi in THEIR Thud client if they want. Someone NOT using Java 1.1.

http://www.unicode.org/reports/tr9/


OK, as well as the above, plus many many pages of scrawled logbook entries, there are 1,643 more lines of code now, bringing the total to the client to a quite scary 8,302 "lines"; 33,382 "words"; 285,640 bytes

Compiled and optimised, though, that's just 20k larger than before, which isn't too bad. Maybe I do have space to stuff in a regex parser after all...

I'm pretty darn proud of some of the speed optimising tweeaks I've put in, and some of the other stuff I've got planned should make the time it takes wrapping your text become prettymuch unnoticeable. In the April Fool's version, it could take up to three seconds PER LINE, but you never noticed much because the main window can't be resized. In this version, it's prettymuch fluidly resizable even with a lengthy text buffer. For some of the future things, I'll need a record of where every letter is on the screen, so I suspect that it'll slow down, but I've some plans for optimisations to at least compensate for that, and possibly even increase the speed.

Anyway, it's 610k less than it could have been if I used an external lib. Is it worth it? I think so, I've ended up with a component that does far closer to what I wanted, rather than having to co-opt some textarea thing.


Dewi Morgan wrote:

OK, as well as the above, plus many many pages of scrawled logbook entries, there are 1,643 more lines of code now, bringing the total to the client to a quite scary 8,302 "lines"; 33,382 "words"; 285,640 bytes

You should only get worried when its longer than the novel Wink

Dewi Morgan wrote:

I'm pretty darn proud of some of the speed optimising tweeaks I've put in, and some of the other stuff I've got planned should make the time it takes wrapping your text become prettymuch unnoticeable. In the April Fool's version, it could take up to three seconds PER LINE, but you never noticed much because the main window can't be resized. In this version, it's prettymuch fluidly resizable even with a lengthy text buffer. For some of the future things, I'll need a record of where every letter is on the screen, so I suspect that it'll slow down, but I've some plans for optimisations to at least compensate for that, and possibly even increase the speed.

On the april fool version it was noticeable slow sending text to the message box i hope the optimisations work.

Dewi Morgan wrote:

Anyway, it's 610k less than it could have been if I used an external lib. Is it worth it? I think so, I've ended up with a component that does far closer to what I wanted, rather than having to co-opt some textarea thing.

Just a comment on the new version the pink is only slightly more readable than the black on the picture background.

And can we have a smaller shared window for those who do not have hi res screens i run at 1280x1024 and can only just fit all the window in if i shrink my task bar so those on 800x600 have real problems using the shared window.

Also fyi the new tools bar only changes the size of the text of the names of users logged in.

SANEAlex


Thanks for the feedback - feedback is Really Important. Particularly because it lets me see what's Really Important to the players rather than to myself.

Generally, to me, getting the stuff done that means I can call each feature "completed in theory, just needs a skinner to come along and impliment it" is most important.

To users, getting the stuff that lets them call each feature "not painful to use" is more important. This is a different but arguably far more important viewpoint. So I might consider limiting of font sizes to be unimportant, while to users, getting spammed, they'd be really vital. I might consider using magenta text an unimportant stopgap to make it visible against the background, while to users, being able to change the text colour is vital.

The magenta text was chosen because it was the best colour to stand out against the now-truly-unsuitable background graphic at top. bottom, and centre. This was checked both by eye and by colour code: it's the one that's farthest from the average hue in each part. I'll get a better graphic, and then be able to use more reasonable text. I also want the user to be able to vary the opacity of the textarea from 0 to 100% in a chosen colour.

The toolbar setting thingus isn't really ready for "primetime" - at the moment it's just a proof-of-concept of the tab layout component, and so that people can see what fonts are available to them. The settings tab eventually needs the following settings, and needs to store them on the server:

  • Default/per-skin textarea opacity and colour [Urgent]
  • Default/per-skin textarea font properties (size, colours, opacity, face and style). [urgent]
    [*] Lots of other stuff I just added to my to-do list because I'd just been holding them in my head.

    For the meantime, I'll halve the size of the applet vertically, which I've wanted to do for some time anyway, and that'll mean that dark blue should stand out better against the light grey, and be less eyebleedey.


  • More feed back here as i cant reply in announce

    The new colour scheme/size is definatly easier on the eyes at least for me thanks.

    The return on name, password to login does work for me now, again thanks.

    Tho i cant see a test button to click on to see board like you said in announce. Tools button gives me

    settings, fonts,about

    settings
    3 tick boxes ask,Display,Play Ok,Apply,Cancel

    Fonts lets me change size of my name in shared box

    About is Blank

    Help, About in shared is also blank may i suggest that if its easy to do you stick a message saying if haveing problems try technical problem pages on forum.thudgame.com

    SA


    Oh yeah, the test board is just in the debug mode, and is triggered by saying somestring (I can't remember what, I put it in at 3am because it was an easy to-do item to get out the way, it's something like "/testboard".)

    Glad the changes worked. I think skins will only affect boards, so we need the actual main central applet to look "finished" since people won't be able to skin it. Which means getting ourselves a decent background graphic that works with the transparency and the new size. Something very light, or very dark, but not a mix of shades.

    The settings dialog (and the help menu, which will be a bunch of links to relevant pages on the site, I think) are the next things to concentrate on. The to-do for the settings dialog is startting to look scary, and the ones for the rich text are starting to look completed.

    However, I've a lady visiting from the US for a fortnight in four days, so I have to work quickly. I want to give her the attention she deserves! Very Happy

    Incidentally, I've only yet seen posts here from admins - are any other users able to see/read/reply-to these posts?


    Founding PatronLibrarianDruidThudmeister

    I could post to this forum before I was a druid (e.g. the follow the tape thread), so I expect everyone can.

    Mr S

    EDIT: spelling & clarity (well, I tried to introduce some anyway Wink)


    Comment viewing options

    Select your preferred way to display the comments and click "Save settings" to activate your changes.