Xojo have a Syntax where Color.Red and Color["Red"] refer to the same thing?

The Color DataType has the constant Red for instance.
With a string “Red”, is there a Syntax to use the string to get Color.Red?
For instance where Color.Red and Color[“Red”] return the same thing?

I have a list of the color name constants for a menu and was hoping to use the text directly to build each MenuItem’s Tag.

you could store the rgb Color into the menuitem .Tag

1 Like

No, there isn’t a way to do this like you’re suggesting. You’l need a Select Case statement:

Select Case colorName
Case "Red"
    theColor = Color.Red
Case "Blue"
    theColor = Color.Blue

…etc. Or you could populate a Dictionary and look it up that way:

Dim ColorLookup as New Dictionary

ColorLookup.Value(ColorConstants.kRedColorName) = Color.Red

...

MenuItem.Tag = ColorLookup.Value(theColorName)
1 Like

Using ColorGroup there is a limited number of system colours that can be called using the (name As String) constructor to return a Color value, on macOS at least. Example:

g.DrawingColor = New ColorGroup("systemRedColor")
...
g.DrawingColor = New ColorGroup("textColor")

On macOS these predefined names are limited to Standard System Colors or UI Element Colors (note: only some of these work, some testing will be required to verify which).

The ColorGroup also allows for “Named” colours that I think you can predefine yourself - though I have not tried that feature yet. Probably worth checking into?

Edited to add: here’s a blog post about using named ColorGroups, for Web projects anyway.

But why would you implement string methods when MenuItem.Tag is a Variant and can store the actual color value?

A color, after all, is what OP said their final goal is.

3 Likes

example

Function ConstructContextualMenu(base As DesktopMenuItem, x As Integer, y As Integer) Handles ConstructContextualMenu as Boolean
  If Me.SelectedText.Trim.BeginsWith("http://")=True Or Me.SelectedText.Trim.BeginsWith("https://")=True Then
    Var open As New DesktopMenuItem(kOpen) 
    open.Icon = MenuIcon(icons8_website_96px)
    base.AddMenu open
  End If
  
  Var c As New Clipboard
  If Me.ReadOnly = False And c.TextAvailable = True Then
    Var insert As New DesktopMenuItem(kPaste) 
    insert.Icon = MenuIcon(icons8_paste_96px)
    base.AddMenu insert
  End If
  
  Var col As New DesktopMenuItem(kColors)
  col.Icon = MenuIcon(icons8_color_palette_96px)
  
  col.AddMenu DesktopMenuItemColor("Rot",Color.Red)
  col.AddMenu DesktopMenuItemColor("Orange",Color.Orange)
  col.AddMenu DesktopMenuItemColor("Gelb",Color.Yellow)
  col.AddMenu DesktopMenuItemColor("Grün",Color.RGB(0,128,0))
  col.AddMenu DesktopMenuItemColor("Blaugrün",Color.Teal)
  col.AddMenu DesktopMenuItemColor("Blau",Color.RGB(0,0,128))
  col.AddMenu DesktopMenuItemColor("Schwarz",Color.Black)
  col.AddMenu DesktopMenuItemColor("Grau",Color.Gray)
  col.AddMenu DesktopMenuItemColor("Braun",Color.Brown) 
  col.AddMenu DesktopMenuItemColor("Violett",Color.Purple)
  col.AddMenu DesktopMenuItemColor("Purpur",Color.Magenta)
  col.AddMenu DesktopMenuItemColor("Türkis",Color.Cyan)
  
  base.AddMenu col
  
  Var style As New DesktopMenuItem("Style")
  style.Icon = MenuIcon(icons8_typography_96px)
  
  style.AddMenu New DesktopMenuItem("Normal")
  style.AddMenu New DesktopMenuItem("Fett")
  style.AddMenu New DesktopMenuItem("Unterstrichen")
  style.AddMenu New DesktopMenuItem("Kursiv")
  style.AddMenu New DesktopMenuItem("Link")
  
  base.AddMenu style
  
  Var gr As New DesktopMenuItem(kSize) ' in Punkte
  gr.Icon = MenuIcon(icons8_resize_vertical_96px)
  
  gr.AddMenu New DesktopMenuItem("10")
  gr.AddMenu New DesktopMenuItem("12")
  gr.AddMenu New DesktopMenuItem("14")
  gr.AddMenu New DesktopMenuItem("16")
  gr.AddMenu New DesktopMenuItem("18")
  gr.AddMenu New DesktopMenuItem("20")
  gr.AddMenu New DesktopMenuItem("22")
  
  base.AddMenu gr
  
  Return True
End Function

Function ContextualMenuItemSelected(selectedItem As DesktopMenuItem) Handles ContextualMenuItemSelected as Boolean
  Select Case selectedItem.Text
  Case "Farbe", "Color", "Rot", "Red", "Orange", "Gelb", "Yellow", "Grün", "Green", "Blau", "Blue", "Schwarz", "Black", "Grau", "Gray", "Grey", "Braun", "Brown", "Purpur", "Magenta", "Türkis", "Cyan", "Violett", "Purple", "Blaugrün", "Teal"
    Me.SelectionTextColor = selectedItem.Tag.ColorValue
  End Select
  
  Select Case selectedItem.Text
  Case "Bold","Fett"
    Me.SelectionBold = True
  Case "Normal"
    Me.SelectionBold = False
    Me.SelectionItalic = False
    Me.SelectionUnderline = False
    Me.SelectionTextColor = Color.Black
    Me.SelectionFontSize = 14 'Points
  Case "Kursiv", "Italic"
    Me.SelectionItalic = True
  Case "Link"
    Me.SelectionTextColor = Color.Blue
    Me.SelectionUnderline = True
  Case "Unterstrichen", "Underlined"
    Me.SelectionUnderline = True
    
  Case "10"
    Me.SelectionFontSize = 10 'Points
  Case "12"
    Me.SelectionFontSize = 12 'Points
  Case "14"
    Me.SelectionFontSize = 14 'Points
  Case "16"
    Me.SelectionFontSize = 16 'Points
  Case "18"
    Me.SelectionFontSize = 18 'Points
  Case "20"
    Me.SelectionFontSize = 20 'Points
  Case "22"
    Me.SelectionFontSize = 22 'Points
    
  Case "Open","Öffnen"
    System.GotoURL(Me.SelectedText.Trim)
    
  Case "Paste","Einfügen"
    Var c As New Clipboard
    If c.TextAvailable Then
      Me.SelectedText = c.Text
    End If
    'Me.Paste <- das fügt was ein was dann nicht gespeichert wird
    
  End Select
  
  RaiseEvent NewSize
  
  Return True
End Function

Perhaps I’ve misunderstood. Looks like he’s trying to get a constant from the Color class by referring to it by name (string), like you might do in a language such as PHP. Obviously that doesn’t work in Xojo, hence the lookup techniques.

Did I miss the mark?

The way I understood the goals, the only reason a String value is being used is for the purpose of storage in the MenuItem.Tag. If that is the case, there is no need for the string step since the Tag is a variant and can store the original Color value.

// This is FAR more simple than the suggested designs
var mnu as new MenuItem("Example")
mnu.Tag = Color.Red
2 Likes

basically its
Var m As New DesktopMenuItem("Example", Color.Red)

the tag in constuctor was my feature request :slight_smile:

unfortunately Color is not a Class and we can NOT use .Tag isA Color

missing method

Public Function DesktopMenuItemColor(tx as Text, tag as Color) As DesktopMenuItem
  Var m As New DesktopMenuItem(tx, tag)
  
  Var pic As New Picture(24,24)
  pic.Graphics.DrawingColor = tag
  pic.Graphics.FillRectangle 0,0,96,96
  
  m.Icon = pic
  
  Return m
End Function

While looking at building a color picker that used color names, I was wondering if this shortcutting syntax style was available:

s = "Black Brown Blue Cyan Teal LightGray Gray DarkGray Green Red Magenta Orange Purple Yellow White Clear"
anArray = s.Split(" ")
For i As Integer = 0 To anArray.LastIndex
  someValue=Color[s(i)]
Next

But, some kind of lookup will be needed and the Tag looks like a flexible tool. The idea is to get a selection of text to know its color’s name (svg name or other palettes names), the way it knows its font name or size. Thanks to everyone for the ideas.

=Color[s(i)]

Dictionary would be ok for this, what Eric wrote.

there are so many color names as example
https://www.w3schools.com/tags/ref_colornames.asp

If that string of names is all you desire, expanding this is the kind of task AI was actually built for :slight_smile:

var base as new MenuItem

// Define the menu items literally using API 2.0
var itemBlack as new MenuItem("Black")
itemBlack.Tag = Color.Black
base.AddMenu(itemBlack)

var itemBrown as new MenuItem("Brown")
itemBrown.Tag = Color.Brown
base.AddMenu(itemBrown)

var itemBlue as new MenuItem("Blue")
itemBlue.Tag = Color.Blue
base.AddMenu(itemBlue)

var itemCyan as new MenuItem("Cyan")
itemCyan.Tag = Color.Cyan
base.AddMenu(itemCyan)

var itemTeal as new MenuItem("Teal")
itemTeal.Tag = Color.Teal
base.AddMenu(itemTeal)

var itemLightGray as new MenuItem("LightGray")
itemLightGray.Tag = Color.LightGray
base.AddMenu(itemLightGray)

var itemGray as new MenuItem("Gray")
itemGray.Tag = Color.Gray
base.AddMenu(itemGray)

var itemDarkGray as new MenuItem("DarkGray")
itemDarkGray.Tag = Color.DarkGray
base.AddMenu(itemDarkGray)

var itemGreen as new MenuItem("Green")
itemGreen.Tag = Color.Green
base.AddMenu(itemGreen)

var itemRed as new MenuItem("Red")
itemRed.Tag = Color.Red
base.AddMenu(itemRed)

var itemMagenta as new MenuItem("Magenta")
itemMagenta.Tag = Color.Magenta
base.AddMenu(itemMagenta)

var itemOrange as new MenuItem("Orange")
itemOrange.Tag = Color.Orange
base.AddMenu(itemOrange)

var itemPurple as new MenuItem("Purple")
itemPurple.Tag = Color.Purple
base.AddMenu(itemPurple)

var itemYellow as new MenuItem("Yellow")
itemYellow.Tag = Color.Yellow
base.AddMenu(itemYellow)

var itemWhite as new MenuItem("White")
itemWhite.Tag = Color.White
base.AddMenu(itemWhite)

var itemClear as new MenuItem("Clear")
itemClear.Tag = Color.Clear
base.AddMenu(itemClear)

Put that into a factory function and your MenuItem tags will be colors!

i had add a feature request (issue) having color as class.

Hmm. Well, he doesn’t elaborate on his goals very much. I was imagining a situation where a user color selection, presented in the menu, is being stored somewhere (a preferences file, database row) as a string and he needed a way to associate the name of the color with the color itself.

Edit: he does elaborate on his goals later in the thread, which I missed when typing this comment. Still relevant enough, I think.

Correct, but because Color is an intrinsic (like integer, for example) and Tag is a Variant, you can test for it like this:

If MenuItem.Tag.Type = Variant.TypeColor Then
    ...
End If
1 Like

you can test for it like this:

good to know :slight_smile:

Just to wrap up:
The use case is for a TextArea and a bevel button in a DesktopContainer. The button’s popup menu allows the user to select a color for any selectd text. Clicking in the TextArea also changes the button’s caption to display the color’s name.
I was going to save the hex_color in the button menu’s Tag and search the menu tags, but that started looking too complicated.
The recommendation to use a Dictionary (as a property of the container) worked well in this case.

Thanks for all the suggestions.

Exactly why you should have stored the color itself. The dictionary was a bad suggestion to you, I’m so sorry. You were given the best answer within 30 minutes by Markus.

Here’s how it’s done, it’s really significantly easier (and safer) than Dictionary:
colortag.xojo_xml_project.zip (4.2 KB)

Sub MenuSelected(selectedItem As MenuItem) Handles MenuSelected
  var cSelection as Color = selectedItem.Tag
  TextArea1.SelectionTextColor = cSelection

End Sub

The approach you show in the code is the most straightforward for the popup. The hex_color is in the Tag and the color_name is in the menu text.
However, the Dictionary, with the color_name and hex_color, is used in the TextArea SelectionChange event.
When the selection changes, the hex_color is used to find the color_name and reset the popup button’s caption.
Searching for the hex_color in the Menu Tags to find the color_name is what looked complicated, so I went this way instead:

Sub Opening() Handles Opening
  // =====  DesktopBevelButton used for color popup
  // =====  make color list Dictionary for this Container
  // ===== it was suggested to use a "Constructor" to build colorDict
  Var aName() As String
  Var s As String
  s = "Black Brown Blue Cyan Teal LightGray Gray DarkGray Green Red Magenta Orange Purple Yellow White Clear"
  aName = s.Split(" ")
  
  Var aColor() As Color
  aColor=Array(Color.Black, Color.Brown, Color.Blue, Color.Cyan, Color.Teal, Color.LightGray, Color.Gray, Color.DarkGray, Color.Green, Color.Red, Color.Magenta, Color.Orange, Color.Purple, Color.Yellow, Color.White, Color.Clear)
  
  Self.colorDict=New Dictionary
  For i As Integer = 0 To aName.LastIndex 
    Self.colorDict.value(aColor(i).ToString)=aName(i)
  Next
  // =====
  
  Var myMenu As New MenuItem
  Var tmpMenu As New MenuItem
  
  Me.Menu=myMenu.Clone  // this assignment prevents errors in the loop when using Me.Menu
  For Each entry As DictionaryEntry In colorDict  //may as well use the dictionary here too
    tmpMenu.Name = entry.Key
    tmpMenu.Text = entry.Value
    tmpMenu.Tag=entry.key
    Me.Menu.AddMenu(tmpMenu) 
  Next 
  
End Sub
Sub SelectionChanged() Handles SelectionChanged

   // TextArea's SelectionChange
  Var s As String=Me.styledtext.FontName(st-1,1) 
  Var a As Variant

  s=Me.StyledText.TextColor(Me.SelectionStart-1,1).toString  // this is the hex value
  a = colorDict.Lookup(s,s)
  tac_FontColor.Caption=a
   
End Sub

Just closing this out.
Thanks to all for the examples and techniques, most of which I was seeing for the first time (and used soon after).
Since this question was originally about language syntax, Eric answered it directly with a “No”.

I used Color as an example since named colors are available, but the question was about if there was a way to replace this kind of code:

Var styles() As Boolean
styles.add(TextArea1.Bold)
styles.add(TextArea1.Italic)
styles.add(TextArea1.Underline)

with something like this where the compiler would see TextArea1[att] as TextArea1.Bold in the loop’s first iteration

Var styles() As Boolean
Var atts() As String = Array("Bold", "Italic", "Underline")
For Each att As String In atts
  styles.add(TextArea1[att]) 
Next