Board index FlightGear Development Canvas

Canvas widget scrollArea tuning

Canvas is FlightGear's new fully scriptable 2D drawing system that will allow you to easily create new instruments, HUDs and even GUI dialogs and custom GUI widgets, without having to write C++ code and without having to rebuild FlightGear.

Canvas widget scrollArea tuning

Postby 5H1N0B1 » Mon Jan 04, 2021 10:57 pm

Hi everyone,
Recently we had somebody that worked a lot on livery for the mirage 2000, so I needed a new selection dialog.
So I'm working on a custom livery selection dialog using the scrollArea.
My wish was to have a something that look like the aircraft selection but for livery : 1 Image, a Title, an a short description of this livery, maybe the associate logos and by able to select it this way.

That in mind I made this :
Image

Which is already a cool rendering. But have few issue :
1) when I'm selecting the wanted livery, I would like to click on the line and have it selected. How can I do that ?
2) As I couldn't done what I made above, I used a "label" widget of the image, and a "button" widget for the selection. I could make the button pressed, like you can see on the picture but as soon as I loose the focus, the button is going up.

This bellow is my code : btw lot in there isn't optimized : this is just for test now. I will then make it object (and make it as easy to use as the gui.Overlay object) :
Code: Select all
# Test prototype
#This needs to be done in OOP : The idea is to implement 3 scollArea in the same window
#more commented and be cleaned
#Need to add the multiplay variable in order to display it (not revelvant for liveries for it is for logos
var scan = func(dir){
        data = [];
        # put an array with files
        var files = directory(dir);
        #If empty just return en empty []
        if (size(files)) {
            #Lokking for each files
            foreach (var file; files) {
                #print(file);
                if (substr(file, -4) != ".xml")
                    continue;
                #reading the file
                var n = io.read_properties(dir ~ file);
                #props.dump(n);
                #print(file);
                #This need to be in variable.
                var IOXML = io.readxml(dir ~ file);
                var name = IOXML.getNode("/PropertyList/sim/model/livery/name",1).getValue();
                var pathPng = IOXML.getNode("/PropertyList/sim/model/livery/texture",1).getValue();
                var logoName = IOXML.getNode("/PropertyList/sim/model/logos/name",1).getValue();
               
                #print(name);
                #print(pathPng);
                #print(logoName);
               
                #props.dump(toto); # dump data
                #var name = nameNode.getValue(); # n.getNode(nameprop, 1).getValue();
                var index = n.getNode("name", 1).getValue();
                #var pathPng = pathPngNode.getValue();
                #var logoName = logoNameNode.getValue();
                if (name == nil)# or index == nil)
                    continue;
                #adding what we want to the array
                append(data, [name, substr(file, 0, size(file) - 4), dir ~ file,pathPng,logoName]);
            }
            #sorting it by name
            data = sort(data, func(a, b) num(a[0]) == nil or num(b[0]) == nil
                   ? cmp(a[0], b[0]) : a[0] - b[0]);
        }
        return data
}



# canvas.showLoadDialog();


#read the property of the xml file above and put it into the props.globals
#io.read_properties(me.data[me.current][3], props.globals); #index is 2

###################### The example bellow is working ##############

#   #Scaning for livery
Livery_dir = "Aircraft/Mirage-2000/Models/Liveries"; # livery path
var Properties_tree_name =  "/sim/model/livery/name";
var Properties_tree_name_MP = "sim/multiplay/model/livery";

var dir = resolvepath(Livery_dir) ~ "/";

# Number of items to display
var num_items = size(scan(dir));
# Define window width and height
var (winwidth,winheight) = (500,(30*0.5*num_items));
# Initialize window variable
var CtrlListWin = nil;

var ListScroll = nil;

var SampleList = [];

var InitList = func() {
   var list = ["Test List"];
   for(var i = 1; i < (num_items+1); i +=1) {   
         append(list, [i, nil]);
    }   
    return list;
}

var InitWindow = func() {
   CtrlListWin = canvas.Window
      .new([winwidth,winheight],"dialog")
      .set('title','Controller Assignments');

   CtrlListWin.del = func() {
       call(canvas.Window.del, [], me);
       #Reset window variable
       CtrlListWin = nil;
   };

   var CtrlListWinCanvas = CtrlListWin.createCanvas()
      .set("background", "#A9A9A9");
   var WinRoot = CtrlListWinCanvas.createGroup();
     
   # Create a vbox as parent to the scroll area
   var list_vbox = canvas.VBoxLayout.new();
   # Add vbox to the main window
   CtrlListWin.setLayout(list_vbox);
   # Create scroll area as a child of the root group
   var scrollarea = canvas.gui.widgets.ScrollArea.new(WinRoot, canvas.style, {size: [winwidth, winheight],focus_policy:2}).move(20, 100);
   # Add scroll area to the vbox
   list_vbox.addItem(scrollarea, 1);
   # Add content item to the scroll area, with style information
   var scrollarea_content = scrollarea.getContent()
          .set("font", "LiberationFonts/LiberationSans-Bold.ttf")
          .set("character-size", 16)
          .set("alignment", "left-center");
   # Add vbox item as child to the scroll area
   var list = canvas.VBoxLayout.new();
   scrollarea.setLayout(list);
   # Add title text
   var label = canvas.gui.widgets.Label.new(scrollarea_content, canvas.style, {wordWrap: 0})
                  .setText(" "~SampleList[0]);
   list.addItem(label);
   #print(size(SampleList));
   
   var _makeListener_button = func(i) {
       return func {
          #debug testing property
          #print(SampleList[i][1]._checkable);
          #setting up the last livery button
          SampleList[selected_Item(data_liveries)][1]._down = 0 ;
          SampleList[selected_Item(data_liveries)][1]._onStateChange();
         
          #setting down the new livery button
          SampleList[i][1]._down = 1 ;
          #writing into the property tree
          io.read_properties(data_liveries[i][2], props.globals);
          #debug testing what has been choosen
          #print("Selected livery : n°" ~ i ~ " : " ~ data_liveries[i][0]);

       };
   }
   

   
   var data_liveries = scan(dir);
   
   # Add vector items to the scroll area content item
   for(var i=1; i < size(SampleList) - 1; i+=1) {
     
      #create a line that will contain all we need
      var row = canvas.HBoxLayout.new();

       
      #adding the row to the scroll List
      list.addItem(row);
     
      # Add a simple label...
      SampleList[i][0] = canvas.gui.widgets.Label.new(scrollarea_content, canvas.style, {})
                  .setFixedSize(220,220)
                  .setImage("Aircraft/Mirage-2000/Models/"~data_liveries[i][3]);
     
                 
      #Adding image to the row
      row.addItem(SampleList[i][0]);
     
      # Add a simple button...
      SampleList[i][1] = canvas.gui.widgets.Button.new(scrollarea_content, canvas.style, {checkable:1})
                   .setText(data_liveries[i][0])
                   .setFixedSize(220,220)
                   .listen("clicked", _makeListener_button(i));
      #Making it checkable
      SampleList[i][1]._checkable = 1;           
      row.addItem(SampleList[i][1]);
      row.addSpacing(5);
     
      #coloration of row
      if(selected_Item(data_liveries) == i){
          SampleList[i][1]._down = 1 ;
          SampleList[i][1]._onStateChange();
          SampleList[i][0]._focused=1;
          SampleList[i][0]._onStateChange();
       #print("Selected livery : n°" ~ i ~ " : " ~ data_liveries[i][0]);
      }
     
   }
     
}

var selected_Item = func(data_liveries){
  # finding the current selection
  for(var i=1; i < size(data_liveries) - 1; i+=1) {
    if(data_liveries[i][0] == getprop(Properties_tree_name)){
      return i;
    }
  }
}

# Window toggling function
var showLiveryDialog = func() {
   if(CtrlListWin == nil) {
      # Initialize list
      SampleList = InitList();
      # Call window initialization function
      InitWindow();
   }
   else {
      CtrlListWin.del();
      # Reset window variable
      CtrlListWin = nil;
   }
}

Well obiously the answer I seek is an answer to the first question. Because it could be really awesome !
Thanks a lot in advance for the help
5H1N0B1
"Each day, with every person you meet, there is something to learn"
5H1N0B1
 
Posts: 222
Joined: Thu Aug 30, 2012 10:36 am
Location: France
Callsign: 5H1N0B1
IRC name: _5H1N0B1
Version: GIT
OS: Ubuntu

Re: Canvas widget scrollArea tuning

Postby Hooray » Tue Jan 05, 2021 12:18 am

I am not sure if I am understanding the question correctly, but if you want to "select" a button, you can use its methods - there also is a dedicated "toggle" button, and a corresponding method. To see for yourself, open $FG_ROOT/Nasal/canvas/gui/widgets/Button.nas
Note that you can also set up a button to show an image directly.
For style handling refer to DefaultStyle.nas in Nasal/canvas/gui/styles

Speaking in general, your dialog looks already pretty good, so I would suggest to consider making it generic, so that it can be used by other aircraft/developers.
That way, you'll also end up with more potential contributors
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Canvas widget scrollArea tuning

Postby wkitty42 » Tue Jan 05, 2021 1:51 pm

why not start with the existing livery selector and modify that to use a canvas instead of text PUI dialog?
then you only need each livery to supply an image, with a specific generic name, that can be displayed if it exists... paint the image on one side of the list and the name on the other... if there is no image, display a generic one like the launcher does...

the reason i suggest to use the existing livery selector is because one only need to create a directory tree in the craft's livery directory tree and provide the base XML... the existing livery selector will automatically pick up the livery and display it for use in the list of available liveries... no reinvention of the wheel necessary...
"You get more air close to the ground," said Angalo. "I read that in a book. You get lots of air low down, and not much when you go up."
"Why not?" said Gurder.
"Dunno. It's frightened of heights, I guess."
User avatar
wkitty42
 
Posts: 9146
Joined: Fri Feb 20, 2015 4:46 pm
Location: central NC, USA
Callsign: wk42
Version: git next
OS: Kubuntu 20.04

Re: Canvas widget scrollArea tuning

Postby 5H1N0B1 » Tue Jan 05, 2021 9:18 pm

Hi,
Both of you thanks for your answers.
@Hooray :
there also is a dedicated "toggle" button

This is exactly what I did.But I must have failed somewhere, because when I click "outside" of the canvas, it "untoogle" the button (this may be linked to the focus thing)
Note that you can also set up a button to show an image directly.
: I didn't know that ! I tried and did not success, so I was starting to believe it is not possible. How do you do that ?
DefaultStyle.nas in Nasal/canvas/gui/styles
All the background stuff are in here ? So if I what to change a background color I need to use this ? (I'm going to check)

Indeed the idea is to make it generic. To answer also to you @wkitty42 I started from the actual livery selector (That is the Object named gui.OverlaySelector that I'm talking about on my first message)
Here I just tried to see what is possible to do in canvas, before anything else. But then, making it generic, I'm highly inspired by the old livery selector. My goal is to make the same object, with the same way of create it : then it could be replaced in other aircraft, without any changes in their own code.

The final result on the mirage would be to have 3 different scroll area in the same windows, but this part is a bit more specific :
1- Livery (Color schemes, event liveries etc)
2-Logos (coutry flag, squadron flag, aircraft serial number
3- Some nose art (and maybe some people want to fly without it)
Some Liveries are very specific to 1 country or one squadron, so for that I need to find a way to indicate which logos have the same story as the livery.

Anyways : I would be pleased if @Hoorray you can show me how : to put a image into a button and not un toogle the button when I lose the windows focus. That would be great !
5H1N0B1
"Each day, with every person you meet, there is something to learn"
5H1N0B1
 
Posts: 222
Joined: Thu Aug 30, 2012 10:36 am
Location: France
Callsign: 5H1N0B1
IRC name: _5H1N0B1
Version: GIT
OS: Ubuntu

Re: Canvas widget scrollArea tuning

Postby Hooray » Tue Jan 05, 2021 10:28 pm

Hi, I'd suggest to take a look at Tom's original Aircraft Center dialog in $FG_ROOT/Nasal/canvas/gui/dialogs/AircraftCenter.nas - you can use that as a reference/example to learn how to do more sophisticated things.
Alternatively, do as I said and open Button.nas to see how to set up the toogle mode and/or background images.
Please don't send support requests by PM, instead post your questions on the forum so that all users can contribute and benefit
Thanks & all the best,
Hooray
Help write next month's newsletter !
pui2canvas | MapStructure | Canvas Development | Programming resources
Hooray
 
Posts: 12707
Joined: Tue Mar 25, 2008 9:40 am
Pronouns: THOU

Re: Canvas widget scrollArea tuning

Postby 5H1N0B1 » Wed Jan 06, 2021 12:05 am

Thanks a lot for your answer.

Well for the record I already dig into AircraftCenter.nas (that's where I found how to put 2 widget on a row and some fun stuff)
I also already dig in Button.nas ... Although I could find a setImage for the "label" I could find it for the "button"...

I dig into those file before even posting on the forum... Maybe I missed something... I'll let you know
5H1N0B1
"Each day, with every person you meet, there is something to learn"
5H1N0B1
 
Posts: 222
Joined: Thu Aug 30, 2012 10:36 am
Location: France
Callsign: 5H1N0B1
IRC name: _5H1N0B1
Version: GIT
OS: Ubuntu


Return to Canvas

Who is online

Users browsing this forum: No registered users and 6 guests