<!--
Copyright Disney Enterprises, Inc.  All rights reserved.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License
 and the following modification to it: Section 6 Trademarks.
 deleted and replaced with:

 6. Trademarks. This License does not grant permission to use the
 trade names, trademarks, service marks, or product names of the
 Licensor and its affiliates, except as required for reproducing
 the content of the NOTICE file.

 You may obtain a copy of the License at
 http://www.apache.org/licenses/LICENSE-2.0
-->

<h2>User Interface Tutorial</h2>
The user interface components included in the SeExpr distribution provide a useful way to visualize the results of your expression evaluations and speed up the process of building expressions.  This tutorial uses some of the main UI components to build a simple app for editing and previewing expressions for image synthesis.

<p>
The finished example code can be found in <a href="./classImageEditorDialog.html">ImageEditorDialog Class Reference</a>.

<p>
See <a href="./mytut.html">Simple ASCII Grapher Tutorial</a> for getting started using SeExpr.

<h2>Problem Overview: Image Synthesis</h2>

We'd like to be able to use a GUI expression editor to preview resulting images as we are building our expressions.  For example, the evaluation of this:

<pre style="padding-left: 5em;">
$val=voronoi(5*[$u,$v,.5],4,.6,.2);
$color=ccurve($val,
    0.000, [0.141, 0.059, 0.051], 4, 
    0.185, [0.302, 0.176, 0.122], 4, 
    0.301, [0.651, 0.447, 0.165], 4,  
    0.462, [0.976, 0.976, 0.976], 4);
$color
</pre>

looks like this:<br><br> <img src="./ui_preview.png">

<p>
In this tutorial, we are going to write an interface for doing image synthesis using expressions.  This example uses the <a href="http://doc.qt.digia.com/4.7/index.html">Qt Toolkit</a> and <a href="./index.html">SeExpr</a> libraries.  See referenced documentation for more detail.

<p>
The components of the interface will include:

<ul>
<li>an expression editor</li>
<li>a panel for control widgets</li>
<li>an expression library browser</li>
<li>an image previewer</li>
</ul>

<h2>Main Dialog</h2>

We will first create a new ImageEditorDialog class based on the <a href="http://doc.qt.digia.com/4.7/qdialog.html">QDialog</a> class:

<pre style="padding-left: 5em;">
#include &lt;QtGui/QDialog&gt;

class ImageEditorDialog: public QDialog
{
public:
    ImageEditorDialog(QWidget *parent=0);
};

ImageEditorDialog::ImageEditorDialog(QWidget *parent)
    :QDialog(parent)
{
    this->setWindowTitle("Image Synthesis Editor");
}
</pre>

A simple main application will show the dialog:

<pre style="padding-left: 5em;">
#include &lt;QtGui/QApplication&gt;
#include "ImageEditorDialog.h"

int main(int argc, char *argv[]){
    QApplication app(argc, argv);
    ImageEditorDialog *dialog = new ImageEditorDialog(0);
    dialog->show();
    app.exec();
    return 0;
}
</pre>

<h2>Widget Controls and Text Editor</h2>

Now let's add some controls and an expression editor.  The <a href="./classSeExprEdControlCollection.html">SeExprEdControlCollection</a> class provides the ability to add UI controls (sliders, ramps, etc.) for various types of variables (int, float, color, curves, etc.).  The <a href="./classSeExprEditor.html">SeExprEditor</a> class provides the ability to manually edit the expression script.
<p>
We will include two new header files, in addition to the needed Qt header files:

<pre style="padding-left: 5em;">
#include &lt;QtGui/QVBoxLayout&gt;
#include &lt;QtGui/QScrollArea&gt;
#include &lt;SeExprEdControlCollection.h&gt;
#include &lt;SeExprEditor.h&gt;
</pre>

and add a private member to the ImageEditorDialog class definition for the editor (we will use the editor's contents later to generate the preview image):

<pre style="padding-left: 5em;">
private:
    SeExprEditor *_editor;
</pre>

Next we'll add 2 new components in the constructor and lay them out.  The <a href="http://doc.qt.digia.com/4.7/qscrollarea.html">QScrollArea</a> has specific parameters to properly display the controls.  The SeExprEditor constructor takes a pointer to the SeExprEdControlCollection object, so it can connect signals between them:

<pre style="padding-left: 5em;">
    // Expression controls
    SeExprEdControlCollection *controls = new SeExprEdControlCollection();
    QScrollArea* scrollArea=new QScrollArea();
    scrollArea->setMinimumHeight(100);
    scrollArea->setFixedWidth(450);
    scrollArea->setWidgetResizable(true);
    scrollArea->setWidget(controls);

    // Expression editor
    _editor = new SeExprEditor(this, controls);

    // Layout widgets
    QVBoxLayout *rootLayout = new QVBoxLayout();
    this->setLayout(rootLayout);
    rootLayout->addWidget(scrollArea);
    rootLayout->addWidget(_editor);
</pre>

Already we can use the demo app to create some expressions.  

<p>
Clicking the <b>Add Widget</b> button will give us a dialog to choose different variable types, with the corresponding expression output displayed in the editor:<br><br><img src="./ui_addWidget.png">

<p>
For example, adding a color widget creates 3 sliders for RGB values which we can edit either from the control sliders or from the text editor:<br><br><img src="./ui_editor1.png">

<h2>Expression Library Browser</h2>

<p>
Next let's add an expression library browser so we can look at example expressions and add our own.  We will use the <a href="./classSeExprEdBrowser.html">SeExprEdBrowser</a> class and connect it to the editor.

<p>
First, we will need an additional header:

<pre style="padding-left: 5em;">
#include &lt;SeExprEdBrowser.h&gt;
</pre>

The browser reads from a config.txt file to locate expression files.  An example can be found in ./build/src/demos/imageEditor/config.txt.  We will create the browser in the ImageEditorDialog constructor:
<pre style="padding-left: 5em;">
    // Expression browser
    SeExprEdBrowser *browser = new SeExprEdBrowser(0, _editor);

    // Add user expressions, example expressions to browser list.
    browser->addUserExpressionPath("imageEditor");
#ifdef IMAGE_EDITOR_ROOT
    std::string exPathStr = IMAGE_EDITOR_ROOT;
    exPathStr += "/share/SeExpr/expressions";
    browser->addPath("Examples", exPathStr);
#else
    browser->addPath("Examples", "./src/demos/imageEditor");
#endif
    browser->update();
</pre>

and adjust the layout to make room for it:

<pre style="padding-left: 5em;">
    // Layout widgets: top section containing left and right, and bottom section
    QVBoxLayout *rootLayout = new QVBoxLayout();
    this->setLayout(rootLayout);

    QWidget* topWidget=new QWidget();
    QHBoxLayout* topLayout=new QHBoxLayout();
    topLayout->setContentsMargins(0,0,0,0);
    topWidget->setLayout(topLayout);

    QWidget *leftWidget=new QWidget();
    QVBoxLayout *leftLayout=new QVBoxLayout();
    leftLayout->setContentsMargins(0,0,0,0);
    leftWidget->setLayout(leftLayout);
    leftLayout->addWidget(scrollArea,1);

    QWidget *bottomWidget=new QWidget();
    QVBoxLayout *bottomLayout=new QVBoxLayout();
    bottomLayout->setContentsMargins(0,0,0,0);
    bottomWidget->setLayout(bottomLayout);

    topLayout->addWidget(leftWidget);
    topLayout->addWidget(browser,1);

    bottomLayout->addWidget(_editor);

    rootLayout->addWidget(topWidget);
    rootLayout->addWidget(bottomWidget);
</pre>

We now have the ability to browse expression files.  Selecting a file from the browser list will load its contents into the editor and create any associated widgets:<br><br><img src="./ui_browser.png">

<h2>Image Previewer</h2>

<p>
The last component is the image previewer.  This borrows heavily from the <a href="./imageSynth_8cpp.html">imageSynth demo code</a>.

<p>
We will use a <a href="http://doc.qt.digia.com/4.7/qlabel.html">QLabel</a> with a pixmap image generated by some of the code from the imageSynth program.

<p>
First some additional headers:

<pre style="padding-left: 5em;">
#include &lt;string&gt;
#include &lt;QtGui/QLabel&gt;
#include &lt;QtGui/QImage&gt;
#include &lt;QtGui/QMessageBox&gt;
</pre>

and another new data member in the ImageEditorDialog class for the image label:

<pre style="padding-left: 5em;">
private:
    QLabel *_imageLabel;
</pre>

We'll create the image label in the constructor and add it to the top left of the layout, above the controls (scrollArea):

<pre style="padding-left: 5em;">
    // Image Previewer
    _imageLabel = new QLabel();
    _imageLabel->setFixedSize(256,256);
    _imageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter );
    QImage image("./src/doc/html/seexprlogo.png"); // just a fun default
    QPixmap imagePixmap = QPixmap::fromImage(image);
    imagePixmap = imagePixmap.scaled(256, 256, Qt::KeepAspectRatio);
    _imageLabel->setPixmap(imagePixmap);

    leftLayout->addWidget(_imageLabel);
    leftLayout->addWidget(scrollArea,1);
</pre>

The layout should nowlook something like this:<br><br><img src="./ui_emptyLayout.png">

<p>
To generate an image preview, we will want to evaluate the contents of the editor.  We'll need to add an apply button that will evaluate the expression.

<p>
First, let's create some classes to handle the image synthesis.  This code is a subset of the imageSynth demo code mentioned earlier.  The differences are that the pixel order is slightly different for generating a <a href="http://doc.qt.digia.com/4.7/qimage.html">QImage</a> than for generating a PNG file, and the evaluateExpression() method returns a pointer to the image rather than writing the image to file.

<pre style="padding-left: 5em;">
#include &lt;png.h&gt;
#include &lt;SeExpression.h&gt;

double clamp(double x){return std::max(0.,std::min(255.,x));}

// Simple image synthesizer expression class to support demo image editor
class ImageSynthExpression:public SeExpression
{
public:
    // Constructor that takes the expression to parse
    ImageSynthExpression(const std::string& expr)
        :SeExpression(expr)
    {}

    // Simple variable that just returns its internal value
    struct Var:public SeExprScalarVarRef
    {
        Var(const double val):val(val){}
        Var(){}
        double val; // independent variable
        void eval(const SeExprVarNode* /*node*/,SeVec3d& result)
        {result[0]=val;}
    };
    // variable map
    mutable std::map&lt;std::string,Var&gt; vars;

    // resolve function that only supports one external variable 'x'
    SeExprVarRef* resolveVar(const std::string& name) const
    {
        std::map&lt;std::string,Var&gt;:iterator i=vars.find(name);
        if(i != vars.end()) return &i->second;
        return 0;
    }
};

class ImageSynthesizer
{
public:
    ImageSynthesizer();
    unsigned char *evaluateExpression(const std::string &exprStr);
private:
    int _width;
    int _height;
};

ImageSynthesizer::ImageSynthesizer()
{
    _width = 256;
    _height = 256;
}

unsigned char *ImageSynthesizer::evaluateExpression(const std::string &exprStr)
{
    ImageSynthExpression expr(exprStr);

    // make variables
    expr.vars["u"]=ImageSynthExpression::Var(0.);
    expr.vars["v"]=ImageSynthExpression::Var(0.);
    expr.vars["w"]=ImageSynthExpression::Var(_width);
    expr.vars["h"]=ImageSynthExpression::Var(_height);

    // check if expression is valid
    bool valid=expr.isValid();
    if(!valid){
        std::cerr&lt;&lt;"Invalid expression "&lt;&lt;std::endl;
        std::cerr&lt;&lt;expr.parseError()&lt;&lt;std::endl;
        return NULL;
    }

    // evaluate expression
    std::cerr&lt;&lt;"Evaluating expression..."&lt;&lt;std::endl;
    unsigned char* image=new unsigned char[_width*_height*4];
    double one_over_width=1./_width,one_over_height=1./_height;
    double& u=expr.vars["u"].val;
    double& v=expr.vars["v"].val;
    unsigned char* pixel=image;
    for(int row=0;row&lt;_height;row++){
        for(int col=0;col&lt;_width;col++){
            u=one_over_width*(col+.5);
            v=one_over_height*(row+.5);
            SeVec3d result=expr.evaluate();
            pixel[0]=clamp(result[0]*256.);
            pixel[1]=clamp(result[1]*256.);
            pixel[2]=clamp(result[2]*256.);
            pixel[3]=255;
            pixel+=4;
        }
    }

    return image;
}
</pre>

Now we're ready to create an apply button and add it to the bottom of the layout:

<pre style="padding-left: 5em;">
#include &lt;QtGui/QPushButton&gt;
#include &lt;QtGui/QMessageBox&gt;

    // Create apply button and connect to image preview.
    QPushButton *applyButton=new QPushButton("Apply");
    connect(applyButton, SIGNAL(clicked()), (ImageEditorDialog*)this, SLOT(applyExpression()));

    QWidget *buttonWidget=new QWidget();
    QHBoxLayout *buttonLayout = new QHBoxLayout(0);
    buttonWidget->setLayout(buttonLayout);
    buttonLayout->addWidget(applyButton);

    bottomLayout->addWidget(_editor);
    bottomLayout->addWidget(buttonWidget);
</pre>

We will need to write the applyExpression() function to call the ImageSynthesizer object to evaluate the expression inside the editor.  First, we need to include the <a href="http://qt-project.org/doc/qt-4.8/moc.html#moc">Q_OBJECT</a> macro in the ImageEditorDialog class definition, since we're going to be connecting signals and slots:

<pre style="padding-left: 5em;">
class ImageEditorDialog: public QDialog
{
    Q_OBJECT
    ...
</pre>

Next, we'll add a new data member for the ImageSynthesizer instance as well as the applyExpression() function to the ImageEditorDialog class definition:

<pre style="padding-left: 5em;">
private:
    ImageSynthesizer *_imageSynthesizer;
private slots:
    void applyExpression();
</pre>

and, initialize _imageSynthesizer in the constructor:

<pre style="padding-left: 5em;">
    _imageSynthesizer = new ImageSynthesizer();
</pre>

Now we can write the function to evaluate the expression and generate a preview image:

<pre style="padding-left: 5em;">
// Apply expression, if any, from the editor contents to the preview image
void ImageEditorDialog::applyExpression()
{
    std::string exprStr = _editor->getExpr();
    if( exprStr.empty() )
    {
        QMessageBox msgBox;
        msgBox.setText("No expression entered in the editor.");
        msgBox.exec();
    } else {
        QImage image(_imageSynthesizer->evaluateExpression(exprStr),
                     256,
                     256,
                     QImage::Format_RGB32);
        if( image.isNull() )
        {
            QMessageBox msgBox;
            msgBox.setText("Error evaluating expression to create preview image.");
            msgBox.exec();
        } else {
            QPixmap imagePixmap = QPixmap::fromImage(image);
            _imageLabel->setPixmap(imagePixmap);
        }
    }
}
</pre>

Finally, we'll have to pull out the ImageEditorDialog class definition into its own header, ImageEditorDialog.h, so the Qt MOC files will build correctly:

<pre style="padding-left: 5em;">
#include &lt;QtGui/QDialog&gt;

class QLabel;
class SeExprEditor;
class ImageSynthesizer;

class ImageEditorDialog: public QDialog
{
    Q_OBJECT
public:
    ImageEditorDialog(QWidget *parent=0);
private:
    QLabel *_imageLabel;
    SeExprEditor *_editor;
    ImageSynthesizer *_imageSynthesizer;
private slots:
    void applyExpression();
};
</pre>

Now we can load expressions from a library, create new expressions manually as well as by creating new controls, and see all our changes in an image preview as we go:<br><br><img src="./ui_final.png">

<p>
A next simple step would be to add a <b>Save</b> button to save expressions from the editor to your own ~/imageEditor/expressions directory.  The library browser will pick these up automatically, based on the context (imageEditor) and the hard-coded directory (expressions).  This exercise is left to the reader to implement.  
