Logo Search packages:      
Sourcecode: whitedune version File versions  Download package

ScriptDialog.cpp

/*
 * ScriptDialog.cpp
 *
 * Copyright (C) 2003 J. "MUFTI" Scheurich
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program (see the file "COPYING" for details); if 
 * not, write to the Free Software Foundation, Inc., 675 Mass Ave, 
 * Cambridge, MA 02139, USA.
 */

#include "stdafx.h"
#include <ctype.h>
#include "ScriptDialog.h"
#include "ScriptEdit.h"
#include "resource.h"
#include "MyString.h"
#include "newline.h"
#include "FieldValue.h"
#include "NodeScript.h"
#include "SFMFTypes.h"
#include "Field.h"
#include "EventIn.h"
#include "EventOut.h"
#include "ExposedField.h"
#include "Element.h"
#include "DuneApp.h"

#define X_SPACING 2
#define Y_SPACING 2

static const char *eventOrField[] = { 
    " ",
    "eventIn",
    "eventOut",
    "field"
};

static const char *SfOrMf[] = { 
    " ",
    "SF",
    "MF"
};

static const char *DataType[] = { 
    " ",
    "Bool",
    "Color",
    "Float",
    "Image",
    "Int32",
    "Node",
    "Rotation",
    "String",
    "Time",
    "Vec2f",
    "Vec3f"
};


static SWND canvas;
static SWND scroll;
static SWND parent_window;

#define XPOS 56
#define YPOS 47
#ifdef WIN32
# define XMAX 388
# define YMAX 160
#else
# define XMAX 388
# define YMAX 210
#endif
#define SCROLL_SIZE 5

static int ymax;

static void
ScriptDialogRedraw(void* data)
{
    SDC     dc = swCreateDC(canvas);
    swSetFGColor(dc, 0xffffff);
    ScriptDialog* dialog = (ScriptDialog*) data;
    dialog->accountYmax();
    swFillRect(dc, 1, 1, XMAX-2, ymax-2);
    swSetFGColor(dc, 0);
    swDrawLine(dc,      0,      0, XMAX-1,   0);
    swDrawLine(dc,      0, ymax-1, XMAX-1, ymax-1);
    swDrawLine(dc,      0,      0,      0, ymax-1);
    swDrawLine(dc, XMAX-1,      0, XMAX-1, ymax-1);
    dialog->drawInterface();
    swDestroyDC(dc);
}

static void
ScriptDialogExposeCallback(void *data, int x, int y, int width, int height)
{
    ScriptDialogRedraw(data);
}

static void
ScriptDialogEnterCallback(void *data, int command)
{
    ScriptDialogRedraw(data);
}

static int fontHeight;
static int selectedText;

static void
ScriptDialogKeyCallback(void *data, int key, int value, int x, int y, 
                        int modifiers)
{
    // Left mouse button down
    if (key == SW_MOUSE1)
       if (value) {
           selectedText = (y  - Y_SPACING) / (fontHeight + Y_SPACING);
           ScriptDialogRedraw(data);
       }
}

static void
ScriptDialogEditorReadyCallback(void *data)
{
    ScriptDialog *dialog = (ScriptDialog *) data;
    dialog->OnEditorReadyCallback();
}

ScriptDialog::ScriptDialog(SWND parent, Node* oldNode)
  : Dialog(parent, IDD_SCRIPT)
{
    parent_window = parent;
    assert (oldNode->getType() == NODE_SCRIPT);
    _scriptNode = (NodeScript *) oldNode;
    _okFlag = false;
    LoadData();
    _canClick = true;
    _scriptEdit = NULL;
    fontHeight = swGetFontHeight(swGetDefaultFont());
    selectedText = -1;
    accountYmax();
}

ScriptDialog::~ScriptDialog()
{
    swDestroyWindow(canvas);
    swDestroyWindow(scroll); 
}

void
ScriptDialog::OnCommand(int id)
{
    if (_canClick) {
        if (id == ID_ADD_EVENT) {
            addEvent();
#ifdef WIN32
            swSetFocus( swGetDialogItem(_dlg, IDC_EVENT_OR_FIELD));
#endif
        } else if (id == ID_DELETE_EVENT)
            deleteEvent();
        else {            
            if (id == ID_CHANGE_EVENT) {
                addEvent(true);
                changeEvent();
            } else if (id == ID_FILE_PREVIEW) {
            addEvent(true);
                TheApp->OnFilePreview(_scriptNode->getScene());
          } else if (id == ID_SCRIPT_EDIT) {
            addEvent(true);
                stopClick();
                _scriptEdit = new ScriptEdit(_scriptNode,_dlg, 
                                             ScriptDialogEditorReadyCallback, 
                                             this);
                _scriptEdit->ecmaScriptEdit();
            } else if (id == IDOK) {
            addEvent(true);
                _okFlag = true;
                if (Validate()) {
                    swEndDialog(IDOK);
                }
            }
        }
    }
}

void
ScriptDialog::OnEditorReadyCallback(void)
{
    if (_scriptEdit != NULL)
        delete  _scriptEdit;
    _scriptEdit = NULL;
    _canClick = true;
    swInvalidateWindow(canvas);
}

void
ScriptDialog::eraseWidgets(void)
{
    swComboBoxSetSelection(swGetDialogItem(_dlg, IDC_EVENT_OR_FIELD),0);
    swComboBoxSetSelection(swGetDialogItem(_dlg, IDC_SF_OR_MF),0);
    swComboBoxSetSelection(swGetDialogItem(_dlg, IDC_DATATYPE),0);
    swSetText(swGetDialogItem(_dlg, IDC_EVENT_NAME), "");
}

void
ScriptDialog::setWidgets(char *eventString, int typeEnum, const char *eventName)
{
    int i;
    char sfOrMf[3] = { '\0' };
    const char *type = typeEnumToString(typeEnum);
    mystrncpy_danger(sfOrMf, type, 2);
    const char *dataType = (strlen(type) > 2) ? &type[2] : "";

    for (i=0;i<(sizeof(eventOrField)/sizeof(const char*));i++)
        if (strcmp(eventString, eventOrField[i]) == 0)
           swComboBoxSetSelection(swGetDialogItem(_dlg, IDC_EVENT_OR_FIELD), i);
    for (i=0;i<(sizeof(SfOrMf)/sizeof(const char*));i++)
        if (strcmp(sfOrMf, SfOrMf[i]) == 0)
           swComboBoxSetSelection(swGetDialogItem(_dlg, IDC_SF_OR_MF), i);
    for (i=0;i<(sizeof(DataType)/sizeof(const char*));i++)
        if (strcmp(dataType, DataType[i]) == 0)
           swComboBoxSetSelection(swGetDialogItem(_dlg, IDC_DATATYPE), i);
    swSetText(swGetDialogItem(_dlg, IDC_EVENT_NAME), eventName);
}


void
ScriptDialog::addEvent(bool onlyTry)
{
    int event = swComboBoxGetSelection(swGetDialogItem(_dlg,
                                                       IDC_EVENT_OR_FIELD));

    int sfmf = swComboBoxGetSelection(swGetDialogItem(_dlg, IDC_SF_OR_MF));
    if (sfmf == 0) return;

    if (event == 0) return;
    int type = swComboBoxGetSelection(swGetDialogItem(_dlg, IDC_DATATYPE));
    if (type == 0) return;
 
    char eventName[1025];
    swGetText(swGetDialogItem(_dlg, IDC_EVENT_NAME), eventName, 1024);
    if (eventName[0] == (char)0) return;

    Proto* proto=_scriptNode->getProto();
    if (proto==NULL)
        return;

    int i;
    bool alreadyUsed = false;
    for (i=0; i < proto->getNumFields(); i++) 
        if (strcmp(eventName, proto->getField(i)->getName()) == 0)
            alreadyUsed = true;
    for (i=0; i < proto->getNumEventIns(); i++) 
        if (strcmp(eventName, proto->getEventIn(i)->getName()) == 0)
            alreadyUsed = true;
    for (i=0; i < proto->getNumEventOuts(); i++)
        if (strcmp(eventName, proto->getEventOut(i)->getName()) == 0)
            alreadyUsed = true;

    if (alreadyUsed) {
        if (onlyTry) 
            return;
        MyString warning = "name \"";
        warning += eventName;
        warning += "\" already in use ";
        swMessageBox(TheApp->mainWnd(), warning, " dune error ", 
                     SW_MB_OK, SW_MB_ERROR);
        return;
    }

    bool invalidChars = false;
    if (isalpha(eventName[0])) {
       for (i=1; i < strlen(eventName); i++)
          if (!isalpha(eventName[i]) && (!isdigit(eventName[i])) &&
               (eventName[i] != '_'))
              invalidChars = true;
    } else
        invalidChars = true;

    if (invalidChars) {
        MyString warning = "name \"";
        warning += eventName;
        warning += "\" contain non allowed characters ";
        swMessageBox(TheApp->mainWnd(), warning, " dune error ", 
                     SW_MB_OK, SW_MB_ERROR);
        return;
    }
    

    MyString typeString = SfOrMf[sfmf];
    typeString += DataType[type];

    int typeEnum = typeStringToEnum(typeString);
    if (typeEnum == -1) {
        MyString warning = "\"";
        warning += strdup(typeString);
        warning += "\" is not a valid VRML97 Datatype";
        swMessageBox(TheApp->mainWnd(), warning, " dune error ", 
                     SW_MB_OK, SW_MB_ERROR);
        return;
    }

    if (strcmp(eventOrField[event],"field") == 0) {
        proto->addField(typeEnum, eventName, typeDefaultValue(typeEnum),0,NULL);
    } else if (strcmp(eventOrField[event],"eventIn") == 0) { 
        proto->addEventIn(typeEnum, eventName); 
    } else if (strcmp(eventOrField[event],"eventOut") == 0) {
        proto->addEventOut(typeEnum, eventName); 
    }
    selectedText = -1;
    _scriptNode->update();

    swInvalidateWindow(canvas);
    eraseWidgets();
}


bool
ScriptDialog::deleteEvent()
{
    Proto* proto = _scriptNode->getProto();
    InterfaceArray *interfaceData = _scriptNode->getInterfaceData();
    if (proto==NULL)
        return false;
    if (selectedText == -1)
        return false;
    for (int i = 0 ; i < interfaceData->size() ; i++) 
        if (i == selectedText) {
            int ind = interfaceData->get(i)->_elementIndex;
            switch (interfaceData->get(i)->_elementEnum) {
              case EL_FIELD_DEF:
                proto->getField(ind)->setFlags(FF_DELETED);
                break;
              case EL_EVENT_IN:
                if (hasRoute(_scriptNode->getInput(ind))) {
                    swMessageBox(TheApp->mainWnd(), "cut routes first", 
                                 " white_dune error ", SW_MB_OK, SW_MB_ERROR);
                    return false;
                }                     
                proto->getEventIn(ind)->setFlags(FF_DELETED);
                break;
              case EL_EVENT_OUT:
                proto->getEventOut(ind)->setFlags(FF_DELETED);
                if (hasRoute(_scriptNode->getOutput(ind))) {
                    swMessageBox(TheApp->mainWnd(), "cut routes first", 
                                 " white_dune error ", SW_MB_OK, SW_MB_ERROR);
                                   
                    return false;
                }
                break;
            }
        }
  
    _scriptNode->update();

    swInvalidateWindow(canvas);
    return true;
}

void
ScriptDialog::changeEvent()
{
    InterfaceArray *interfaceData = _scriptNode->getInterfaceData();
    Proto* proto=_scriptNode->getProto();
    if (proto==NULL)
        return;
    if (selectedText == -1)
        return;
    char *eventOrField = "";
    int typeEnum;
    const char *name = "";
    bool lineFound = false;
    for (int i = 0 ; i < interfaceData->size() ; i++) 
        if (i == selectedText) {
            lineFound = true;
            int ind = interfaceData->get(i)->_elementIndex;
            switch (interfaceData->get(i)->_elementEnum) {
              case EL_FIELD_DEF:
                eventOrField = "field";
                typeEnum = proto->getField(ind)->getType();
                name = proto->getField(ind)->getName();
                break;
              case EL_EVENT_IN:
                eventOrField = "eventIn";
                typeEnum = proto->getEventIn(ind)->getType();
                name = proto->getEventIn(ind)->getName();
                break;
              case EL_EVENT_OUT:
                eventOrField = "eventOut";
                typeEnum = proto->getEventOut(ind)->getType();
                name = proto->getEventOut(ind)->getName();
                break;
            }
        }
     if (lineFound)
         if (deleteEvent()) {
             setWidgets(eventOrField, typeEnum, name);
         } else {
             eraseWidgets();
         }
}

bool
ScriptDialog::Validate()
{
    return true;
}

void
ScriptDialog::LoadData()
{
    int i;

    SWND comboEventOrField = swGetDialogItem(_dlg, IDC_EVENT_OR_FIELD);
    swComboBoxDeleteAll(comboEventOrField);
    for (i=0;i<(sizeof(eventOrField)/sizeof(const char*));i++)
        swComboBoxAppendItem(comboEventOrField, eventOrField[i]);

    SWND comboSfOrMf = swGetDialogItem(_dlg, IDC_SF_OR_MF);
    swComboBoxDeleteAll(comboSfOrMf);
    for (i=0;i<(sizeof(SfOrMf)/sizeof(const char*));i++)
        swComboBoxAppendItem(comboSfOrMf, SfOrMf[i]);

    SWND comboDataType = swGetDialogItem(_dlg, IDC_DATATYPE);
    swComboBoxDeleteAll(comboDataType);
    for (i=0;i<(sizeof(DataType)/sizeof(const char*));i++)
        swComboBoxAppendItem(comboDataType, DataType[i]);

    scroll = swCreateScrolledWindow(XPOS, YPOS, XMAX-XPOS, YMAX-YPOS, _dlg);
    canvas = swCreateCanvas("scriptdialog", 0, 0, XMAX, YMAX, scroll);
    swScrolledWindowSetChild(scroll, canvas);
    swSetScrollSizes(scroll, XMAX-XPOS-SCROLL_SIZE, YMAX-YPOS-SCROLL_SIZE);

    swSetClientData(canvas, this);
    swSetEnterCallback(canvas, ScriptDialogEnterCallback);
    swSetKeyCallback(canvas, ScriptDialogKeyCallback);
    swSetExposeCallback(canvas, ScriptDialogExposeCallback);
    swInvalidateWindow(canvas);

    swShowWindow(canvas);
}

void 
ScriptDialog::accountYmax()
{
    InterfaceArray *interfaceData = _scriptNode->getInterfaceData();
    ymax = (interfaceData->size() + 1) * (Y_SPACING + fontHeight) +
           2 * Y_SPACING; 
    if (ymax > YMAX-YPOS-SCROLL_SIZE) {
        swSetScrollSizes(scroll, XMAX-XPOS-SCROLL_SIZE, ymax);
        swSetSize(canvas, XMAX-XPOS-SCROLL_SIZE, ymax);
    } else {
        ymax = YMAX-YPOS-SCROLL_SIZE;
        swSetScrollSizes(scroll, XMAX-XPOS-SCROLL_SIZE, YMAX-YPOS-SCROLL_SIZE);
    }
}   


// display type and name of array of dynamic field's, eventIn's and eventOut's 
// of ScriptNode

void 
ScriptDialog::drawInterface()
{
    InterfaceArray *interfaceData = _scriptNode->getInterfaceData();
    SDC dc = swCreateDC(canvas);
    if (!_canClick) {
        swSetFGColor(dc, SW_RED(0xFFFFFF));
        swDrawText(dc, X_SPACING, Y_SPACING + fontHeight, "editor is running");
        return;
    }
    Proto* proto = _scriptNode->getProto();
    if (proto == NULL)
        return;
    int y = 0;
    for (int i = 0 ; i < interfaceData->size() ; i++) {
        MyString text = "";
        int ind = interfaceData->get(i)->_elementIndex;
        switch (interfaceData->get(i)->_elementEnum) {
          case EL_FIELD_DEF:
            text += "field ";
            text += typeEnumToString(proto->getField(ind)->getType());
            text += " ";
            text += proto->getField(ind)->getName();
            break;
          case EL_EVENT_OUT:
            text += "eventOut ";
            text += typeEnumToString(proto->getEventOut(ind)->getType());
            text += " ";
            text += proto->getEventOut(ind)->getName();
            break;
          case EL_EVENT_IN:
            text += "eventIn ";
            text += typeEnumToString(proto->getEventIn(ind)->getType());
            text += " ";
            text += proto->getEventIn(ind)->getName();
            break;
        }  
        y += Y_SPACING + fontHeight;
        if (selectedText == i)
            swSetFGColor(dc, swGetWindowColor(parent_window, 
                                             SW_COLOR_HIGHLIGHT));
        else
            swSetFGColor(dc, swGetWindowColor(parent_window, SW_COLOR_TEXT));
        swDrawText(dc, X_SPACING, y, (const char*) text);
    }
    swDestroyDC(dc);
}


Generated by  Doxygen 1.6.0   Back to index