Merge "Fix for TextField clipping." into devel/master
authorPaul Wisbey <p.wisbey@samsung.com>
Tue, 7 Jul 2015 14:53:54 +0000 (07:53 -0700)
committerGerrit Code Review <gerrit@review.vlan103.tizen.org>
Tue, 7 Jul 2015 14:53:54 +0000 (07:53 -0700)
18 files changed:
node-addon/binding.gyp [new file with mode: 0644]
node-addon/build/Release/dali.node [new file with mode: 0755]
node-addon/build/Release/obj.target/dali.node [new file with mode: 0755]
node-addon/build/binding.Makefile [new file with mode: 0644]
node-addon/build/config.gypi [new file with mode: 0644]
node-addon/build/dali.target.mk [new file with mode: 0644]
node-addon/dali-addon.cpp [new file with mode: 0644]
node-addon/javascript-application-options.cpp [new file with mode: 0644]
node-addon/javascript-application-options.h [new file with mode: 0644]
node-addon/package.json [new file with mode: 0644]
node-addon/test.js [new file with mode: 0644]
plugins/dali-script-v8/src/actors/actor-wrapper.cpp
plugins/dali-script-v8/src/actors/actor-wrapper.h
plugins/dali-script-v8/src/dali-wrapper.cpp
plugins/dali-script-v8/src/dali-wrapper.h
plugins/dali-script-v8/src/module-loader/module-loader.cpp
plugins/dali-script-v8/src/module-loader/module-loader.h
plugins/dali-script-v8/src/utils/v8-utils.cpp

diff --git a/node-addon/binding.gyp b/node-addon/binding.gyp
new file mode 100644 (file)
index 0000000..d8f07f5
--- /dev/null
@@ -0,0 +1,76 @@
+{
+  "variables": {
+    'DALI_JS_DIR%':'../plugins/dali-script-v8/src/'
+  },
+  "targets": [
+    {
+      'target_name': 'dali',
+      'include_dirs': ['<(DALI_JS_DIR)/',
+                       '<(DALI_JS_DIR)/utils'],
+      'sources': [ 'dali-addon.cpp',
+      'javascript-application-options.cpp',
+      '<(DALI_JS_DIR)/utils/v8-utils.cpp',
+      '<(DALI_JS_DIR)/dali-wrapper.cpp',
+      '<(DALI_JS_DIR)/shared/base-wrapped-object.cpp',
+      '<(DALI_JS_DIR)/shared/object-template-helper.cpp',
+      '<(DALI_JS_DIR)/actors/actor-wrapper.cpp',
+      '<(DALI_JS_DIR)/actors/actor-api.cpp',
+      '<(DALI_JS_DIR)/actors/layer-api.cpp',
+      '<(DALI_JS_DIR)/actors/image-actor-api.cpp',
+      '<(DALI_JS_DIR)/actors/camera-actor-api.cpp',
+      '<(DALI_JS_DIR)/constants/constants-wrapper.cpp',
+      '<(DALI_JS_DIR)/animation/animation-api.cpp',
+      '<(DALI_JS_DIR)/animation/animation-wrapper.cpp',
+      '<(DALI_JS_DIR)/animation/constrainer-api.cpp',
+      '<(DALI_JS_DIR)/animation/linear-constrainer-wrapper.cpp',
+      '<(DALI_JS_DIR)/animation/path-api.cpp',
+      '<(DALI_JS_DIR)/animation/path-constrainer-wrapper.cpp',
+      '<(DALI_JS_DIR)/animation/path-wrapper.cpp',
+      '<(DALI_JS_DIR)/stage/stage-wrapper.cpp',
+      '<(DALI_JS_DIR)/events/event-object-generator.cpp',
+      '<(DALI_JS_DIR)/events/pan-gesture-detector-api.cpp',
+      '<(DALI_JS_DIR)/events/pan-gesture-detector-wrapper.cpp',
+      '<(DALI_JS_DIR)/stage/stage-api.cpp',
+      '<(DALI_JS_DIR)/shader-effects/shader-effect-api.cpp',
+      '<(DALI_JS_DIR)/shader-effects/shader-effect-wrapper.cpp',
+      '<(DALI_JS_DIR)/image/image-wrapper.cpp',
+      '<(DALI_JS_DIR)/image/image-api.cpp',
+      '<(DALI_JS_DIR)/image/buffer-image-api.cpp',
+      '<(DALI_JS_DIR)/image/native-image-api.cpp',
+      '<(DALI_JS_DIR)/image/frame-buffer-image-api.cpp',
+      '<(DALI_JS_DIR)/image/resource-image-api.cpp',
+      '<(DALI_JS_DIR)/image/nine-patch-image-api.cpp',
+      '<(DALI_JS_DIR)/object/handle-wrapper.cpp',
+      '<(DALI_JS_DIR)/object/property-value-wrapper.cpp',
+      '<(DALI_JS_DIR)/signals/signal-manager.cpp',
+      '<(DALI_JS_DIR)/render-tasks/render-task-list-api.cpp',
+      '<(DALI_JS_DIR)/render-tasks/render-task-list-wrapper.cpp',
+      '<(DALI_JS_DIR)/render-tasks/render-task-api.cpp',
+      '<(DALI_JS_DIR)/render-tasks/render-task-wrapper.cpp',
+      '<(DALI_JS_DIR)/toolkit/builder/builder-api.cpp',
+      '<(DALI_JS_DIR)/toolkit/builder/builder-wrapper.cpp',
+      '<(DALI_JS_DIR)/toolkit/focus-manager/keyboard-focus-manager-api.cpp',
+      '<(DALI_JS_DIR)/toolkit/focus-manager/keyboard-focus-manager-wrapper.cpp',
+      '<(DALI_JS_DIR)/signals/dali-any-javascript-converter.cpp',
+      '<(DALI_JS_DIR)/garbage-collector/garbage-collector.cpp',
+      '<(DALI_JS_DIR)/module-loader/module.cpp',
+      '<(DALI_JS_DIR)/module-loader/module-loader.cpp'
+     ],
+      'cflags': [
+            '-fPIC',
+            '-frtti',
+            '<!@(pkg-config --cflags dali dali-toolkit)'
+        ],
+
+    'cflags_cc': [
+            '-fexceptions', # Enable exception handler
+            '-frtti'    # needed for typeinfo with dali-any
+        ],
+      'ldflags': [
+            '<!@(pkg-config --libs-only-L --libs-only-other dali dali-toolkit)'
+        ],
+      'libraries': [
+        '<!@(pkg-config --libs-only-l dali dali-toolkit)'
+      ]
+    }]
+}
diff --git a/node-addon/build/Release/dali.node b/node-addon/build/Release/dali.node
new file mode 100755 (executable)
index 0000000..3d5c61d
Binary files /dev/null and b/node-addon/build/Release/dali.node differ
diff --git a/node-addon/build/Release/obj.target/dali.node b/node-addon/build/Release/obj.target/dali.node
new file mode 100755 (executable)
index 0000000..3d5c61d
Binary files /dev/null and b/node-addon/build/Release/obj.target/dali.node differ
diff --git a/node-addon/build/binding.Makefile b/node-addon/build/binding.Makefile
new file mode 100644 (file)
index 0000000..2e10c88
--- /dev/null
@@ -0,0 +1,6 @@
+# This file is generated by gyp; do not edit.
+
+export builddir_name ?= ./build/.
+.PHONY: all
+all:
+       $(MAKE) dali
diff --git a/node-addon/build/config.gypi b/node-addon/build/config.gypi
new file mode 100644 (file)
index 0000000..050745d
--- /dev/null
@@ -0,0 +1,46 @@
+# Do not edit. File was generated by node-gyp's "configure" step
+{
+  "target_defaults": {
+    "cflags": [],
+    "default_configuration": "Release",
+    "defines": [],
+    "include_dirs": [],
+    "libraries": []
+  },
+  "variables": {
+    "clang": 0,
+    "gcc_version": 46,
+    "host_arch": "x64",
+    "icu_small": "false",
+    "node_install_npm": "true",
+    "node_prefix": "",
+    "node_shared_cares": "false",
+    "node_shared_http_parser": "false",
+    "node_shared_libuv": "false",
+    "node_shared_openssl": "false",
+    "node_shared_v8": "false",
+    "node_shared_zlib": "false",
+    "node_tag": "",
+    "node_use_dtrace": "false",
+    "node_use_etw": "false",
+    "node_use_mdb": "false",
+    "node_use_openssl": "true",
+    "node_use_perfctr": "false",
+    "openssl_no_asm": 0,
+    "python": "/usr/bin/python",
+    "target_arch": "x64",
+    "uv_library": "static_library",
+    "uv_parent_path": "/deps/uv/",
+    "uv_use_dtrace": "false",
+    "v8_enable_gdbjit": 0,
+    "v8_enable_i18n_support": 0,
+    "v8_no_strict_aliasing": 1,
+    "v8_optimized_debug": 0,
+    "v8_random_seed": 0,
+    "v8_use_snapshot": "true",
+    "want_separate_host_toolset": 0,
+    "nodedir": "/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4",
+    "copy_dev_lib": "true",
+    "standalone_static_library": 1
+  }
+}
diff --git a/node-addon/build/dali.target.mk b/node-addon/build/dali.target.mk
new file mode 100644 (file)
index 0000000..d2acf12
--- /dev/null
@@ -0,0 +1,201 @@
+# This file is generated by gyp; do not edit.
+
+TOOLSET := target
+TARGET := dali
+DEFS_Debug := \
+       '-DNODE_GYP_MODULE_NAME=dali' \
+       '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-DBUILDING_NODE_EXTENSION' \
+       '-DDEBUG' \
+       '-D_DEBUG'
+
+# Flags passed to all source files.
+CFLAGS_Debug := \
+       -fPIC \
+       -pthread \
+       -Wall \
+       -Wextra \
+       -Wno-unused-parameter \
+       -m64 \
+       -fPIC \
+       -frtti \
+       -I/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/include/dali \
+       -I/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/include \
+       -g \
+       -O0
+
+# Flags passed to only C files.
+CFLAGS_C_Debug :=
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Debug := \
+       -fno-rtti \
+       -fno-exceptions \
+       -fexceptions \
+       -frtti
+
+INCS_Debug := \
+       -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/src \
+       -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/deps/uv/include \
+       -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/deps/v8/include \
+       -I$(srcdir)/../plugins/dali-script-v8/src \
+       -I$(srcdir)/../plugins/dali-script-v8/src/utils
+
+DEFS_Release := \
+       '-DNODE_GYP_MODULE_NAME=dali' \
+       '-D_LARGEFILE_SOURCE' \
+       '-D_FILE_OFFSET_BITS=64' \
+       '-DBUILDING_NODE_EXTENSION'
+
+# Flags passed to all source files.
+CFLAGS_Release := \
+       -fPIC \
+       -pthread \
+       -Wall \
+       -Wextra \
+       -Wno-unused-parameter \
+       -m64 \
+       -fPIC \
+       -frtti \
+       -I/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/include/dali \
+       -I/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/include \
+       -O3 \
+       -ffunction-sections \
+       -fdata-sections \
+       -fno-tree-vrp \
+       -fno-omit-frame-pointer
+
+# Flags passed to only C files.
+CFLAGS_C_Release :=
+
+# Flags passed to only C++ files.
+CFLAGS_CC_Release := \
+       -fno-rtti \
+       -fno-exceptions \
+       -fexceptions \
+       -frtti
+
+INCS_Release := \
+       -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/src \
+       -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/deps/uv/include \
+       -I/home/likewise-open/SERILOCAL/nick.holland/.node-gyp/0.12.4/deps/v8/include \
+       -I$(srcdir)/../plugins/dali-script-v8/src \
+       -I$(srcdir)/../plugins/dali-script-v8/src/utils
+
+OBJS := \
+       $(obj).target/$(TARGET)/dali-addon.o \
+       $(obj).target/$(TARGET)/javascript-application-options.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/utils/v8-utils.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/dali-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/shared/base-wrapped-object.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/shared/object-template-helper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/actors/actor-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/actors/actor-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/actors/layer-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/actors/image-actor-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/actors/camera-actor-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/constants/constants-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/animation-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/animation-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/constrainer-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/linear-constrainer-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/path-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/path-constrainer-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/animation/path-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/stage/stage-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/events/event-object-generator.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/events/pan-gesture-detector-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/events/pan-gesture-detector-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/stage/stage-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/shader-effects/shader-effect-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/shader-effects/shader-effect-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/image-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/image-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/buffer-image-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/native-image-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/frame-buffer-image-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/resource-image-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/image/nine-patch-image-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/object/handle-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/object/property-value-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/signals/signal-manager.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/render-tasks/render-task-list-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/render-tasks/render-task-list-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/render-tasks/render-task-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/render-tasks/render-task-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/toolkit/builder/builder-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/toolkit/builder/builder-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/toolkit/focus-manager/keyboard-focus-manager-api.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/toolkit/focus-manager/keyboard-focus-manager-wrapper.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/signals/dali-any-javascript-converter.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/garbage-collector/garbage-collector.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/module-loader/module.o \
+       $(obj).target/$(TARGET)/../plugins/dali-script-v8/src/module-loader/module-loader.o
+
+# Add to the list of files we specially track dependencies for.
+all_deps += $(OBJS)
+
+# CFLAGS et al overrides must be target-local.
+# See "Target-specific Variable Values" in the GNU Make manual.
+$(OBJS): TOOLSET := $(TOOLSET)
+$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE))
+$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE))  $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE))
+
+# Suffix rules, putting all outputs into $(obj).
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD
+       @$(call do_cmd,cxx,1)
+
+# Try building from generated source, too.
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD
+       @$(call do_cmd,cxx,1)
+
+$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cpp FORCE_DO_CMD
+       @$(call do_cmd,cxx,1)
+
+# End of this set of suffix rules
+### Rules for final target.
+LDFLAGS_Debug := \
+       -pthread \
+       -rdynamic \
+       -m64 \
+       -L/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/lib
+
+LDFLAGS_Release := \
+       -pthread \
+       -rdynamic \
+       -m64 \
+       -L/home/likewise-open/SERILOCAL/nick.holland/dali-env/opt/lib
+
+LIBS := \
+       -ldali-adaptor \
+       -ldali-toolkit \
+       -ldali-core
+
+$(obj).target/dali.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))
+$(obj).target/dali.node: LIBS := $(LIBS)
+$(obj).target/dali.node: TOOLSET := $(TOOLSET)
+$(obj).target/dali.node: $(OBJS) FORCE_DO_CMD
+       $(call do_cmd,solink_module)
+
+all_deps += $(obj).target/dali.node
+# Add target alias
+.PHONY: dali
+dali: $(builddir)/dali.node
+
+# Copy this to the executable output path.
+$(builddir)/dali.node: TOOLSET := $(TOOLSET)
+$(builddir)/dali.node: $(obj).target/dali.node FORCE_DO_CMD
+       $(call do_cmd,copy)
+
+all_deps += $(builddir)/dali.node
+# Short alias for building this executable.
+.PHONY: dali.node
+dali.node: $(obj).target/dali.node $(builddir)/dali.node
+
+# Add executable to "all" target.
+.PHONY: all
+all: $(builddir)/dali.node
+
diff --git a/node-addon/dali-addon.cpp b/node-addon/dali-addon.cpp
new file mode 100644 (file)
index 0000000..8c28eec
--- /dev/null
@@ -0,0 +1,163 @@
+/* Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// EXTERNAL INCLUDES
+#include <node.h>
+#include <public-api/dali-core.h>
+#include <dali-toolkit/dali-toolkit.h>
+#include <integration-api/core.h>
+#include <integration-api/adaptors/adaptor.h>
+#include <public-api/adaptor-framework/window.h>
+#include <devel-api/adaptor-framework/singleton-service.h>
+
+// INTERNAL INCLUDES
+#include <dali-wrapper.h>
+#include "javascript-application-options.h"
+
+using namespace Dali;
+
+namespace DaliNodeAddon
+{
+
+class DaliApplication
+{
+public:
+
+    DaliApplication()
+    : mInitialized( false),
+      mSingletonService(SingletonService::New()),
+      mAdaptor( NULL )
+    {
+    }
+
+    ~DaliApplication()
+    {
+      mSingletonService.UnregisterAll();
+      delete mAdaptor;
+      mWindow.Reset();
+    }
+
+    bool Initialized() const
+    {
+      return mInitialized;
+    }
+
+    void Initialize(  ApplicationOptions options )
+    {
+      if( mInitialized )
+      {
+        return;
+      }
+
+      // 1. Create the window ( adaptor requires a window)
+      const WindowOptions& window( options.window);
+
+      mWindow = Window::New( window.positionSize, window.name, window.transparent );
+
+      // 2. create the adaptor
+      Adaptor* adaptor = &Adaptor::New( mWindow );
+
+      // 3. start the adaptor
+      adaptor->Start();
+
+      // Set the view modes
+
+      if( options.stereo.viewMode > Dali::MONO )
+      {
+        adaptor->SetStereoBase( options.stereo.stereoBase );
+        adaptor->SetViewMode( options.stereo.viewMode );
+      }
+
+      // fire the scene create signal
+      adaptor->SceneCreated();
+
+      mInitialized = true;
+    }
+private:
+
+    bool mInitialized;
+    SingletonService mSingletonService;
+    Adaptor* mAdaptor;
+    Window mWindow;
+
+};
+
+DaliApplication app;
+
+void CreateDali(const v8::FunctionCallbackInfo<v8::Value>& args)
+{
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::HandleScope scope(isolate);
+
+  ApplicationOptions options;
+
+  bool ok = GetApplicationOptions( args, options);
+  if (!ok )
+  {
+    isolate->ThrowException( v8::Exception::TypeError( v8::String::NewFromUtf8(isolate, "Please check arguments passed to DALi require") ) );
+    return;
+  }
+
+  app.Initialize( options );
+
+  // the return value from calling the function   require('dali.js)(  options )
+  // is the dali object
+  args.GetReturnValue().Set( V8Plugin::DaliWrapper::CreateWrapperForNodeJS( isolate ) );
+}
+
+
+/**
+ * We make module.exports a function so that the developer can pass to
+ * parameters to DALi when it's 'required'
+ * E.g
+ *
+ *
+ * var window= {
+ *        x:10,
+ *        y:10,
+ *        width:800,
+ *        height: 600,
+ *        transparent: false,
+ *        name:'my-first-dali-app'
+ * };
+ *
+ * var viewMode {
+ *       'stereoscopic-mode':'stereo-vertical', // mono, stereo-horizontal, stereo-vertical, stereo-interlaced,
+ *       'stereo-base': 65 // Distance in millimeters between left/right cameras typically between (50-70mm)
+ * };
+ *
+ * var options= {
+ *    'window': window,
+ *    'view-mode': viewMode,
+ *    'style-sheet': 'my-theme.json'
+ * }
+ *
+ * var dali = require('dali.js')( options )
+ *
+ *
+ */
+void ExportDaliModule(v8::Handle<v8::Object> exports, v8::Handle<v8::Object> module)
+{
+  NODE_SET_METHOD(module, "exports", CreateDali);
+}
+
+} // namespace DaliNodeAddon
+
+NODE_MODULE(dali, DaliNodeAddon::ExportDaliModule)
+
+
+
+
diff --git a/node-addon/javascript-application-options.cpp b/node-addon/javascript-application-options.cpp
new file mode 100644 (file)
index 0000000..7811583
--- /dev/null
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+// HEADER
+#include "javascript-application-options.h"
+
+// EXTERNAL INCLUDES
+#include <cstring>
+
+// INTERNAL INCLUDES
+#include <v8-utils.h>
+
+namespace DaliNodeAddon
+{
+
+namespace
+{
+
+struct StereoInfo
+{
+  const char* const name;
+  Dali::ViewMode mode;
+};
+StereoInfo StereoModeTable[] = {
+    { "mono",                 Dali::MONO},
+    { "stereo-horizontal",    Dali::STEREO_HORIZONTAL },
+    { "stereo-vertical",      Dali::STEREO_VERTICAL },
+    { "stereo-interlaced",    Dali::STEREO_INTERLACED },
+};
+
+const unsigned int numberViewModes = sizeof( StereoModeTable ) / sizeof( StereoModeTable[0] );
+
+bool GetViewMode( const std::string& modeString, Dali::ViewMode& mode )
+{
+  for( unsigned int i = 0; i < numberViewModes; ++i )
+  {
+    const StereoInfo& info (StereoModeTable[i]);
+
+    if( strcmp ( modeString.c_str() , info.name ) == 0 )
+    {
+      mode = info.mode;
+      return true;
+    }
+  }
+  // mode not found
+  mode = Dali::MONO;
+  return false;
+}
+
+
+// Note we can't parse the enviroment options for window width / height because
+// adaptor which holds the environment option class has not been created
+// and we can't create it, until we have a window
+bool ParseWindowOptions( v8::Isolate* isolate, const v8::Local<v8::Object>& obj,  WindowOptions& window )
+{
+  v8::HandleScope scope(isolate);
+
+  v8::Local<v8::Value> xValue = obj->Get( v8::String::NewFromUtf8( isolate, "x" ) );
+  v8::Local<v8::Value> yValue = obj->Get( v8::String::NewFromUtf8( isolate, "y" ) );
+  v8::Local<v8::Value> widthValue = obj->Get( v8::String::NewFromUtf8( isolate, "width" ) );
+  v8::Local<v8::Value> heightValue = obj->Get( v8::String::NewFromUtf8( isolate, "height" ) );
+  v8::Local<v8::Value> nameValue = obj->Get( v8::String::NewFromUtf8( isolate, "name" ) );
+  v8::Local<v8::Value> transparencyValue = obj->Get( v8::String::NewFromUtf8( isolate, "transparent" ) );
+
+  // if x,y are optional
+  if( xValue->IsUint32() )
+  {
+    window.positionSize.x = xValue->ToUint32()->Value();
+  }
+  if( yValue->IsUint32() )
+  {
+    window.positionSize.y = yValue->ToUint32()->Value();
+  }
+
+  // width and height are optional but will only accept them if they are both set
+  if( widthValue->IsUint32() &&  heightValue->IsUint32() )
+  {
+    window.positionSize.width = widthValue->ToUint32()->Value();
+    window.positionSize.height = heightValue->ToUint32()->Value();
+  }
+
+  // get the window name
+  if( nameValue->IsString() )
+  {
+    window.name = Dali::V8Plugin::V8Utils::v8StringToStdString( nameValue );
+  }
+  else
+  {
+    window.name ="DALi application";
+  }
+
+  if( transparencyValue->IsBoolean() )
+  {
+    window.transparent = transparencyValue->ToBoolean()->Value();
+  }
+  return true;
+}
+
+bool ParseStereoScopicOptions( v8::Isolate* isolate, const v8::Local<v8::Object>& stereoObject,  StereoScopicOptions& options )
+{
+  v8::HandleScope scope(isolate);
+
+  v8::Local<v8::Value> modeValue = stereoObject->Get( v8::String::NewFromUtf8( isolate, "stereoscopic-mode" ) );
+  v8::Local<v8::Value> stereoBaseValue = stereoObject->Get( v8::String::NewFromUtf8( isolate, "stereo-base" ) );
+
+  if( !modeValue->IsString() )
+  {
+    return true;
+  }
+
+  std::string mode = Dali::V8Plugin::V8Utils::v8StringToStdString( modeValue );
+  bool ok = GetViewMode( mode,  options.viewMode);
+  if( !ok )
+  {
+    return false;
+  }
+  if( stereoBaseValue->IsNumber() )
+  {
+    options.stereoBase = stereoBaseValue->ToNumber()->Value();
+  }
+
+  return true;
+}
+
+} // unnamed namespace
+
+bool GetApplicationOptions(const v8::FunctionCallbackInfo<v8::Value>& args, ApplicationOptions& options )
+{
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::HandleScope scope(isolate);
+  bool ok( false );
+
+  if( !args[ 0 ]->IsObject() )
+  {
+    return false;
+  }
+
+  v8::Local<v8::Object> object = args[ 0 ]->ToObject();
+
+  // get the window settings
+  v8::Local<v8::Value> windowValue= object->Get( v8::String::NewFromUtf8( isolate, "window" ) );
+  if( windowValue->IsObject() )
+  {
+    ok = ParseWindowOptions( isolate, windowValue->ToObject(), options.window );
+    if( !ok )
+    {
+      return false; // missing window size
+    }
+  }
+
+  // get the stereoscopic settings
+  v8::Local<v8::Value> stereoValue= object->Get( v8::String::NewFromUtf8( isolate, "view-mode" ) );
+  if( stereoValue->IsObject() )
+  {
+    ok = ParseStereoScopicOptions( isolate,  stereoValue->ToObject(), options.stereo );
+    if( !ok )
+    {
+      return false;  // incorrect stereoscopic mode
+    }
+  }
+
+  // get the style sheet
+  v8::Local<v8::Value> stylesheetValue= object->Get( v8::String::NewFromUtf8( isolate, "style-sheet" ) );
+  if( stylesheetValue->IsString() )
+  {
+    options.stylesheet = Dali::V8Plugin::V8Utils::v8StringToStdString( stylesheetValue );
+  }
+
+  return true;
+}
+
+} // namespace DaliNodeAddon
diff --git a/node-addon/javascript-application-options.h b/node-addon/javascript-application-options.h
new file mode 100644 (file)
index 0000000..56c92fe
--- /dev/null
@@ -0,0 +1,76 @@
+#ifndef __DALI_JAVASCRIPT_APPLICATION_OPTIONS_H__
+#define __DALI_JAVASCRIPT_APPLICATION_OPTIONS_H__
+
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+#include <public-api/dali-core.h>
+#include <public-api/adaptor-framework/window.h>
+#include <v8.h>
+
+namespace DaliNodeAddon
+{
+
+struct WindowOptions
+{
+  WindowOptions()
+  : positionSize(0,0,0,0)
+  {
+  }
+
+  std::string name;
+  Dali::PositionSize positionSize;
+  bool transparent:1;
+};
+
+struct StereoScopicOptions
+{
+  StereoScopicOptions()
+  : viewMode(Dali::MONO),
+    stereoBase(65.f)
+  {
+  }
+
+  Dali::ViewMode viewMode;
+  float stereoBase;
+};
+
+struct ApplicationOptions
+{
+  WindowOptions window;
+  StereoScopicOptions stereo;
+  std::string stylesheet;
+};
+
+/**
+ * @brief parse the dali JavaScript application options
+ * The options are passed to dali when require is called.
+ * E.g. var dali.require('dali.js)(  {options object}  )
+ *
+ * @param[in] args JavaScript arguments
+ * @param[out] options assigned Dali options
+ * @return true on success, false on failure
+ *
+ */
+bool GetApplicationOptions( const v8::FunctionCallbackInfo<v8::Value>& args, ApplicationOptions& options );
+
+
+} // namespace DaliNodeAddon
+
+
+
+#endif // __DALI_JAVASCRIPT_APPLICATION_OPTIONS_H__
diff --git a/node-addon/package.json b/node-addon/package.json
new file mode 100644 (file)
index 0000000..9314a16
--- /dev/null
@@ -0,0 +1,25 @@
+{
+  "name": "dali",
+  "version": "0.0.0",
+  "description": "DALi 3D Engine addon",
+  "main": "index.js",
+  "gypfile": "true",
+  "scripts": {
+     "preinstall" : "./configure",
+     "install" : "make && make install",
+    "test" : "node test.js"
+  },
+  "repository": {
+    "type": "git",
+    "url": "review.tizen.org:29418/platform/core/uifw/dali-core"
+  },
+  "keywords": [
+    "dali",
+    "3D",
+    "engine",
+    "OpenGL",
+    "user interface"
+  ],
+  "author": "Samsung",
+  "license": "http://www.apache.org/licenses/LICENSE-2.0"
+}
diff --git a/node-addon/test.js b/node-addon/test.js
new file mode 100644 (file)
index 0000000..b3abe08
--- /dev/null
@@ -0,0 +1,149 @@
+ var window= {
+        x:800,
+         y:500,
+       width:880,
+       height: 1020,
+       transparent: false,
+       name:'my-first-dali-app'
+ };
+var viewMode={
+       'stereoscopic-mode':'mono', // stereo-horizontal, stereo-vertical, stereo-interlaced,
+       'stereo-base': 65 // Distance in millimeters between left/right cameras typically between (50-70mm)
+ };
+ var options= {
+    'window': window,
+    'view-mode': viewMode,
+ }
+
+var dali = require('./build/Release/dali')( options );
+var netflixRoulette = require('netflix-roulette');
+
+
+var NUMBER_OF_IMAGES = 40; // for now use 16 ( demo files go up to 30)
+var DEMO_IMAGES = []; // array to store Dali Images
+var VIDEO_WALL_ACTORS = []; // array to store Image actors
+var VIDEO_WALL_ROWS = 5; // use 3 rows for the video wall
+var VIDEO_WALL_COLUMNS = 6; // use 12 columns for the video wall
+var VIDEO_WALL_TOTAL_ITEMS = VIDEO_WALL_COLUMNS * VIDEO_WALL_ROWS; // total items
+var VIDEO_WALL_ITEM_SIZE = 128; // width / height of a item in the video wall
+var BORDER_SIZE = 5;
+var VIDEO_WALL_ITEM_SIZE_NO_BORDER = VIDEO_WALL_ITEM_SIZE - BORDER_SIZE;
+var VIDEO_WALL_WIDTH = VIDEO_WALL_COLUMNS * VIDEO_WALL_ITEM_SIZE;
+var VIDEO_WALL_HEIGHT = VIDEO_WALL_ROWS * VIDEO_WALL_ITEM_SIZE;
+var daliApp = {};
+var posters = [];
+
+var wallRootActor; // the root actor of the video wall
+
+
+daliApp.loadNetflixImages = function() {
+
+  if( NUMBER_OF_IMAGES >= VIDEO_WALL_TOTAL_ITEMS)
+  {
+    NUMBER_OF_IMAGES = VIDEO_WALL_TOTAL_ITEMS-1;
+  }
+
+  for (index = 0; index < NUMBER_OF_IMAGES; ++index) {
+
+    fileName = posters[ index % (posters.length-1)  ];
+    if ( fileName )
+    {
+      DEMO_IMAGES[index] = new dali.ResourceImage( { url:fileName } );
+    }
+  }
+}
+
+
+daliApp.createRootActor = function() {
+    wallRootActor = new dali.Actor();
+    wallRootActor.parentOrigin = dali.CENTER;
+    wallRootActor.anchorPoint = dali.CENTER;
+    dali.stage.add(wallRootActor);
+
+    var field = new dali.Control("TextField");
+    field.parentOrigin = dali.CENTER;
+    field.anchorPoint = dali.CENTER;
+
+    field.placeholderText = "DALi netflix netflix-roulette demo";
+    dali.stage.add( field );
+}
+
+
+
+daliApp.getWallActorIndex = function(x, y) {
+    return x + y * VIDEO_WALL_COLUMNS;
+}
+
+daliApp.createActors = function() {
+    daliApp.createRootActor();
+
+    var anim = new dali.Animation(1);
+    var animOptions = {
+      alpha: "linear",
+      delay: 0.0,     // used to delay the start of the animation
+      duration: 1,    // duration of the animation
+     };
+
+    for (y = 0; y < VIDEO_WALL_ROWS; ++y) {
+        for (x = 0; x < VIDEO_WALL_COLUMNS; ++x) {
+
+            var actorIndex = daliApp.getWallActorIndex(x, y);
+            var imageActor = new dali.ImageActor();
+
+            // wrap image index between 0 and NUMBER_OF_IMAGES
+            var imageIndex = actorIndex % NUMBER_OF_IMAGES;
+
+            imageActor.setImage(DEMO_IMAGES[imageIndex]);
+
+            imageActor.parentOrigin = dali.CENTER;
+            imageActor.anchorPoint = dali.CENTER;
+            imageActor.size = [VIDEO_WALL_ITEM_SIZE_NO_BORDER, VIDEO_WALL_ITEM_SIZE_NO_BORDER, 1.0]; // start with zero size so it zooms up
+
+            var xPosition = x * VIDEO_WALL_ITEM_SIZE;
+            //  as the middle the wall is at zero (relative to wallRootActor), we need to subtract half the wall width.
+            // + add half item size because the item anchor point is the center of the wallRootActor.
+            xPosition = xPosition - (VIDEO_WALL_WIDTH / 2) + (VIDEO_WALL_ITEM_SIZE / 2);
+
+            var yPosition = y * VIDEO_WALL_ITEM_SIZE;
+            yPosition = yPosition - (VIDEO_WALL_HEIGHT / 2) + (VIDEO_WALL_ITEM_SIZE / 2);
+
+            imageActor.position = [0,0,0];
+
+            animOptions.delay+=0.25;
+            anim.animateTo( imageActor,"position",[xPosition, yPosition, 0.0],animOptions);
+            // store the actor
+            VIDEO_WALL_ACTORS[actorIndex] = imageActor;
+
+            // Add to the video wall root actor.
+            wallRootActor.add(imageActor);
+        }
+    }
+    anim.play();
+}
+
+function Initialise() {
+
+    daliApp.loadNetflixImages();
+
+    daliApp.createActors();
+}
+
+function actorLoaded( error, data )
+{
+  for( i = 0; i < data.length; ++i )
+  {
+    var entry = data[i];
+
+   if( entry.poster )
+    {
+      posters.push(entry.poster);
+      //console.log(" entry = " + entry.poster );
+    }
+  }
+  Initialise();
+
+}
+
+
+netflixRoulette.actor('nicolas', actorLoaded );
+
index 704c2d1..7b9b158 100644 (file)
@@ -39,7 +39,6 @@ v8::Persistent<v8::ObjectTemplate> ActorWrapper::mActorTemplate;
 v8::Persistent<v8::ObjectTemplate> ActorWrapper::mImageActorTemplate;
 v8::Persistent<v8::ObjectTemplate> ActorWrapper::mCameraActorTemplate;
 v8::Persistent<v8::ObjectTemplate> ActorWrapper::mLayerActorTemplate;
-v8::Persistent<v8::ObjectTemplate> ActorWrapper::mTextLabelTemplate;
 
 namespace
 {
@@ -61,8 +60,7 @@ const ActorTemplate ActorTemplateLookup[]=
     { &ActorWrapper::mActorTemplate },        // ACTOR
     { &ActorWrapper::mImageActorTemplate },   // IMAGE_ACTOR
     { &ActorWrapper::mLayerActorTemplate },   // LAYER_ACTOR
-    { &ActorWrapper::mCameraActorTemplate},   // CAMERA_ACTOR
-    { &ActorWrapper::mTextLabelTemplate }
+    { &ActorWrapper::mCameraActorTemplate}    // CAMERA_ACTOR
 };
 
 /**
@@ -89,6 +87,7 @@ struct ActorApiStruct
 
 /**
  * Lookup table to match a actor type with a constructor and supported API's.
+ * HandleWrapper::ActorType is used to index this table
  */
 const ActorApiStruct ActorApiLookup[]=
 {
@@ -96,8 +95,6 @@ const ActorApiStruct ActorApiLookup[]=
   {"ImageActor", ActorWrapper::IMAGE_ACTOR,  ImageActorApi::New,  ACTOR_API | IMAGE_ACTOR_API   },
   {"Layer",      ActorWrapper::LAYER_ACTOR,  LayerApi::New,       ACTOR_API | LAYER_API                                },
   {"CameraActor",ActorWrapper::CAMERA_ACTOR, CameraActorApi::New, ACTOR_API | CAMERA_ACTOR_API                         },
-  {"TextLabel",  ActorWrapper::TEXT_LABEL,   TextLabelApi::New,   ACTOR_API },
-
 };
 
 const unsigned int ActorApiLookupCount = sizeof(ActorApiLookup)/sizeof(ActorApiLookup[0]);
@@ -118,20 +115,8 @@ Actor CreateActor( const v8::FunctionCallbackInfo< v8::Value >& args,
   // if we don't currently support the actor type, then use type registry to create it
   if( actorType == ActorWrapper::UNKNOWN_ACTOR )
   {
-    Dali::TypeInfo typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( typeName );
-    if( typeInfo ) // handle, check if it has a value
-    {
-      Dali::BaseHandle handle = typeInfo.CreateInstance();
-      if( handle )
-      {
-        actor = Actor::DownCast( handle );
-      }
-    }
-    else
-    {
-      DALI_SCRIPT_EXCEPTION(args.GetIsolate(),"Unknown actor type");
+      DALI_SCRIPT_EXCEPTION( args.GetIsolate(), "Unknown actor type" );
       return Actor();
-    }
   }
   else
   {
@@ -440,6 +425,42 @@ void ActorWrapper::NewActor( const v8::FunctionCallbackInfo< v8::Value >& args)
   args.GetReturnValue().Set( localObject );
 }
 
+void ActorWrapper::NewControl( const v8::FunctionCallbackInfo< v8::Value >& args)
+{
+  v8::Isolate* isolate = args.GetIsolate();
+  v8::HandleScope handleScope( isolate );
+
+  if( !args.IsConstructCall() )
+  {
+    DALI_SCRIPT_EXCEPTION( isolate, "constructor called without 'new" );
+    return;
+  }
+
+  bool found( false );
+  std::string controlName = V8Utils::GetStringParameter( PARAMETER_0, found, isolate,  args );
+
+  if( !found )
+  {
+    DALI_SCRIPT_EXCEPTION( isolate, "missing control name" );
+    return;
+  }
+  Actor control;
+  Dali::TypeInfo typeInfo = Dali::TypeRegistry::Get().GetTypeInfo( controlName );
+  if( typeInfo ) // handle, check if it has a value
+  {
+    Dali::BaseHandle handle = typeInfo.CreateInstance();
+    if( handle )
+    {
+      control = Actor::DownCast( handle );
+    }
+  }
+
+  v8::Local<v8::Object> localObject = WrapActor( isolate, control, ACTOR );
+
+  args.GetReturnValue().Set( localObject );
+}
+
+
 /**
  * given an actor type name, e.g. ImageActor returns the type, e.g. ActorWrapper::IMAGE_ACTOR
  */
index 06b2e06..13cd811 100644 (file)
@@ -41,17 +41,17 @@ class ActorWrapper : public HandleWrapper
 public:
 
   /**
-   * Actor type used an index
+   * Actor type used an index.
+   * These enums are used to index the ActorApiLookup table in actor-wrapper.cpp.
+   * Any changes made must be reflected in the ActorApiLookup otherwise it may segfault when creating an actor
    */
   enum ActorType
   {
     UNKNOWN_ACTOR = -1,
-    ACTOR       = 0,
-    IMAGE_ACTOR  =1,
-    MESH_ACTOR   =2,
-    LAYER_ACTOR  =3,
-    CAMERA_ACTOR =4,
-    TEXT_LABEL   =5
+    ACTOR        = 0,
+    IMAGE_ACTOR  = 1,
+    LAYER_ACTOR  = 2,
+    CAMERA_ACTOR = 3
   };
 
   /**
@@ -77,6 +77,13 @@ public:
   static void NewActor( const v8::FunctionCallbackInfo< v8::Value >& args);
 
   /**
+   * @brief Creates a new Control wrapped inside a Javascript Object.
+   * @note: the control type is passed as a parameter e.g. 'TextField'
+   * @param[in] args v8 function call arguments interpreted
+   */
+  static void NewControl( const v8::FunctionCallbackInfo< v8::Value >& args);
+
+  /**
    * @brief Wraps an actor of a given type
    */
   static v8::Handle<v8::Object> WrapActor(v8::Isolate* isolate, Dali::Actor actor,ActorType actorType);
@@ -89,10 +96,8 @@ public:
   // The Actor ObjectTemplates.
   static v8::Persistent<v8::ObjectTemplate> mActorTemplate;
   static v8::Persistent<v8::ObjectTemplate> mImageActorTemplate;
-  static v8::Persistent<v8::ObjectTemplate> mMeshActorTemplate;
   static v8::Persistent<v8::ObjectTemplate> mCameraActorTemplate;
   static v8::Persistent<v8::ObjectTemplate> mLayerActorTemplate;
-  static v8::Persistent<v8::ObjectTemplate> mTextLabelTemplate;
 
   /**
    * @return the wrapped actor
index 93c85fc..c716f75 100644 (file)
@@ -68,7 +68,7 @@ const ApiFunction ConstructorFunctionTable[]=
     { "MeshActor",          ActorWrapper::NewActor },
     { "CameraActor",        ActorWrapper::NewActor },
     { "Layer",              ActorWrapper::NewActor },
-    { "TextView",           ActorWrapper::NewActor },
+    { "Control",            ActorWrapper::NewControl },
     { "ResourceImage",      ImageWrapper::NewImage },
     { "BufferImage",        ImageWrapper::NewImage },
     { "NinePatchImage",     ImageWrapper::NewImage },
@@ -99,8 +99,9 @@ Integration::Log::Filter* gLogExecuteFilter( Integration::Log::Filter::New(Debug
 bool DaliWrapper::mInstanceCreated = false;
 DaliWrapper* DaliWrapper::mWrapper = NULL;
 
-DaliWrapper::DaliWrapper()
-:mIsolate( NULL )
+DaliWrapper::DaliWrapper( RunMode runMode, v8::Isolate* isolate )
+:mIsolate( isolate ),
+ mRunMode(runMode)
 {
 }
 
@@ -111,20 +112,60 @@ DaliWrapper::~DaliWrapper()
 
 DaliWrapper& DaliWrapper::Get()
 {
-  if(!mInstanceCreated)
+  if( !mInstanceCreated )
   {
-    mWrapper = new DaliWrapper();
+    mWrapper = new DaliWrapper( RUNNING_STANDALONE, NULL );
+
     mInstanceCreated = true;
 
-    if(mWrapper)
-    {
-      mWrapper->Initialize();
-    }
-  }
+    mWrapper->InitializeStandAlone();
 
+  }
   return *mWrapper;
 }
 
+v8::Local<v8::Object> DaliWrapper::CreateWrapperForNodeJS( v8::Isolate* isolate )
+{
+  v8::EscapableHandleScope handleScope( isolate);
+
+  mInstanceCreated = true;
+
+  mWrapper = new DaliWrapper( RUNNING_IN_NODE_JS, isolate );
+
+  v8::Local<v8::Object> dali = mWrapper->CreateDaliObject();
+
+  // As we running inside node, we already have an isolate and context
+  return handleScope.Escape( dali );
+}
+
+v8::Local<v8::Object>  DaliWrapper::CreateDaliObject()
+{
+  v8::EscapableHandleScope handleScope( mIsolate  );
+
+  // Create dali object used for creating objects, and accessing constant values
+  // e.g. var x =  new dali.Actor(), or var col = dali.COLOR_RED;
+
+  v8::Local<v8::ObjectTemplate> daliObjectTemplate = NewDaliObjectTemplate( mIsolate );
+
+  // add dali.staqe
+  v8::Local<v8::Object> stageObject = StageWrapper::WrapStage( mIsolate, Stage::GetCurrent() );
+  daliObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "stage") , stageObject );
+
+  v8::Local<v8::Object> keyboardObject = KeyboardFocusManagerWrapper::WrapKeyboardFocusManager( mIsolate,Toolkit::KeyboardFocusManager::Get() );
+  daliObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "keyboardFocusManager") , keyboardObject );
+
+
+  //create an instance of the template
+  v8::Local<v8::Object> daliObject = daliObjectTemplate->NewInstance();
+
+  ConstantsWrapper::AddDaliConstants( mIsolate, daliObject);
+
+  daliObject->Set( v8::String::NewFromUtf8( mIsolate,  "V8_VERSION") ,v8::String::NewFromUtf8( mIsolate, v8::V8::GetVersion() ));
+
+  return handleScope.Escape( daliObject  );
+}
+
+
 void DaliWrapper::SetFlagsFromString(const std::string &flags)
 {
   v8::V8::SetFlagsFromString(flags.c_str(), flags.size());
@@ -132,6 +173,12 @@ void DaliWrapper::SetFlagsFromString(const std::string &flags)
 
 void DaliWrapper::Shutdown()
 {
+  // if we're running inside node then we don't have ownership of the context
+  if( mRunMode == RUNNING_IN_NODE_JS )
+  {
+    return;
+  }
+
   DALI_LOG_WARNING("Destroying V8 DALi context\n");
 
   if( !mContext.IsEmpty())
@@ -160,35 +207,33 @@ GarbageCollectorInterface& DaliWrapper::GetDaliGarbageCollector()
   return mGarbageCollector;
 }
 
-void DaliWrapper::CreateContext( )
+void DaliWrapper::ApplyGlobalObjectsToContext( v8::Local<v8::Context> context )
 {
   v8::HandleScope handleScope( mIsolate );
 
-  // Create a  global JavaScript object so we can set built-in global functions, like Log.
-  v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New( mIsolate );
+  // Add global objects ( functions/ values ) e.g. log function
+  // create a console.log and console.error functions
+  v8::Local<v8::ObjectTemplate> consoleObjectTemplate = v8::ObjectTemplate::New( mIsolate );
+  consoleObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "log"),   v8::FunctionTemplate::New( mIsolate, V8Utils::Log));
+  consoleObjectTemplate->Set( v8::String::NewFromUtf8( mIsolate, "error"), v8::FunctionTemplate::New( mIsolate, V8Utils::LogError));
 
-  // Add global objects ( functions/ values ) e.g. log function and V8_VERSION
-  global->Set( v8::String::NewFromUtf8( mIsolate,  "log"),        v8::FunctionTemplate::New( mIsolate, V8Utils::Log) );
-  global->Set( v8::String::NewFromUtf8( mIsolate,  "logError"),   v8::FunctionTemplate::New( mIsolate, V8Utils::LogError) );
-  global->Set( v8::String::NewFromUtf8( mIsolate,  "require"),    v8::FunctionTemplate::New( mIsolate, DaliWrapper::Require));
-  global->Set( v8::String::NewFromUtf8( mIsolate,  "V8_VERSION") ,v8::String::NewFromUtf8( mIsolate, v8::V8::GetVersion() ));
+  context->Global()->Set( v8::String::NewFromUtf8( mIsolate, "console"), consoleObjectTemplate->NewInstance() );
 
-   // add the dali object to it, assume it won't be garbage collected until global is deleted
-  global->Set(v8::String::NewFromUtf8( mIsolate, DALI_API_NAME) ,  NewDaliObjectTemplate( mIsolate ));
+  // add require functionality
+  context->Global()->Set( v8::String::NewFromUtf8( mIsolate, "require"), v8::FunctionTemplate::New( mIsolate, DaliWrapper::Require)->GetFunction());
 
+  // Create the Dali object
+  // @todo consider forcing developers to perform require('dali') if we want to avoid polluting the global namespace
+  v8::Local<v8::Object> daliObject = CreateDaliObject();
 
-  // create a new context.
-  // Isolate = isolated copy of the V8 including a heap manager, a garbage collector
-  // Only 1 thread can access a single Isolate at a given time. However, multiple Isolates can be run in parallel.
-  // Context = multiple contexts can exist in a given Isolate, and share data between contexts
-  v8::Handle<v8::Context> context  = v8::Context::New( mIsolate, NULL, global);
+  // allow developers to require('dali'); // this is to maintain compatibility with node.js where dali is not part of the global namespace
+  mModuleLoader.StorePreBuiltModule( mIsolate, daliObject, DALI_API_NAME );
 
-  mGlobalObjectTemplate.Reset( mIsolate,  global);
+  context->Global()->Set( v8::String::NewFromUtf8( mIsolate, DALI_API_NAME),daliObject );
 
-  mContext.Reset( mIsolate, context);
 }
 
-void DaliWrapper::Initialize()
+void DaliWrapper::InitializeStandAlone()
 {
   if( !mIsolate )
   {
@@ -198,38 +243,35 @@ void DaliWrapper::Initialize()
 
     // default isolate removed from V8 version 3.27.1 and beyond.
     mIsolate = v8::Isolate::New();
+
     mIsolate->Enter();
 
     v8::V8::SetFatalErrorHandler( FatalErrorCallback );
-
   }
+
   // if context is null, create it and add dali object to the global object.
   if( mContext.IsEmpty())
   {
      v8::HandleScope handleScope( mIsolate );
-     CreateContext();
-     v8::Local<v8::Context> context = v8::Local<v8::Context>::New(mIsolate, mContext);
-
-     context->Enter();
 
-     // Add the dali global object. Used for creating objects, and accessing constant values
-     // e.g. var x =  new dali.ImageActor(), or var col = dali.COLOR_RED;
+     // create a new context.
+     // Isolate = isolated copy of the V8 including a heap manager, a garbage collector
+     // Only 1 thread can access a single Isolate at a given time. However, multiple Isolates can be run in parallel.
+     // Context = multiple contexts can exist in a given Isolate, and share data between contexts
+     v8::Local<v8::Context> context  = v8::Context::New( mIsolate );
 
-     v8::Local<v8::Object> daliObject = v8::Local<v8::Object>::Cast( context->Global()->Get( v8::String::NewFromUtf8( mIsolate, DALI_API_NAME)));
-
-     v8::Local<v8::Object> stageObject = StageWrapper::WrapStage( mIsolate, Stage::GetCurrent() );
-     daliObject->Set( v8::String::NewFromUtf8( mIsolate, "stage") , stageObject );
-
-     // keyboard focus manager is a singleton
-     v8::Local<v8::Object> keyboardObject = KeyboardFocusManagerWrapper::WrapKeyboardFocusManager( mIsolate,Toolkit::KeyboardFocusManager::Get() );
-     daliObject->Set( v8::String::NewFromUtf8( mIsolate, "keyboardFocusManager") , keyboardObject );
+     context->Enter();
 
-     ConstantsWrapper::AddDaliConstants( mIsolate, daliObject);
+     // Apply global objects like dali and console to the context
+     ApplyGlobalObjectsToContext(context);
 
+     mContext.Reset( mIsolate, context);
   }
+
   DALI_LOG_INFO( gLogExecuteFilter, Debug::Verbose, "V8 Library %s loaded \n", v8::V8::GetVersion() );
 }
 
+
 v8::Handle<v8::ObjectTemplate> DaliWrapper::NewDaliObjectTemplate( v8::Isolate* isolate )
 {
   v8::EscapableHandleScope handleScope( isolate );
@@ -241,11 +283,11 @@ v8::Handle<v8::ObjectTemplate> DaliWrapper::NewDaliObjectTemplate( v8::Isolate*
   objTemplate->Set( v8::String::NewFromUtf8( isolate, "BUILD"),
                     v8::String::NewFromUtf8( isolate, "Dali binary built on:" __DATE__ ", at " __TIME__));
 
-
+#ifdef DALI_DATA_READ_ONLY_DIR
   // add the data data directory,
   objTemplate->Set( v8::String::NewFromUtf8( isolate, "DALI_DATA_DIRECTORY"),
-                      v8::String::NewFromUtf8( isolate, DALI_DATA_READ_ONLY_DIR));
-
+                    v8::String::NewFromUtf8( isolate, DALI_DATA_READ_ONLY_DIR));
+#endif
   // add our constructor functions
   ObjectTemplateHelper::InstallFunctions( isolate,
                                           objTemplate,
@@ -259,12 +301,10 @@ v8::Handle<v8::ObjectTemplate> DaliWrapper::NewDaliObjectTemplate( v8::Isolate*
 void DaliWrapper::Require(const v8::FunctionCallbackInfo< v8::Value >& args)
 {
   DaliWrapper& wrapper( DaliWrapper::Get() );
-  wrapper.mModuleLoader.Require( args, wrapper.mGlobalObjectTemplate );
+  wrapper.mModuleLoader.Require( args );
 }
 
 
-
-
 } // namespace V8Plugin
 
 } // namespace Dali
index e576f4b..f1767e4 100644 (file)
@@ -24,6 +24,7 @@
 
 // INTERNAL INCLUDES
 #include <garbage-collector/garbage-collector.h>
+
 #include <module-loader/module-loader.h>
 
 namespace Dali
@@ -65,12 +66,25 @@ namespace V8Plugin
  */
 class DALI_INTERNAL DaliWrapper
 {
+
 public:
 
   /**
-   * Constructor
+   * @brief whether the wrapper is running in standalone using V8,
+   * or inside Node.JS using V8
    */
-  DaliWrapper();
+  enum RunMode
+  {
+    RUNNING_STANDALONE,
+    RUNNING_IN_NODE_JS
+  };
+
+  /**
+   * @brief Constructor
+   * @param[in] runMode whether the wrapper is running standalone or inside Node.JS
+   * @param[in] isolate v8 isolate ( can be null if running standalone )
+   */
+  DaliWrapper( RunMode runMode, v8::Isolate* isolate );
 
   /**
    * non virtual destructor, not intended as a base class
@@ -85,6 +99,12 @@ public:
   static DaliWrapper& Get();
 
   /**
+   * Intialize DaliWrapper for running inside NodeJS
+   */
+  static v8::Local<v8::Object> CreateWrapperForNodeJS( v8::Isolate* isolate);
+
+
+  /**
    * Set V8 engine configuration flags
    *
    * @param[in] flags Configruation flags (See v8 documentation)
@@ -124,14 +144,21 @@ public:
 private:
 
   /**
-   * Create V8 context
+   * @brief Apply global objects like console.log and require() to the context
    */
-  void CreateContext();
+  void ApplyGlobalObjectsToContext( v8::Local<v8::Context> context );
 
   /**
-   * Initialize DaliWrapper
+   * @brief Initialize DaliWrapper for running standalone
+   * Creates a new isolate
+   *
    */
-  void Initialize();
+  void InitializeStandAlone();
+
+  /**
+   * @brief create dali namespace/object
+   */
+  v8::Local<v8::Object> CreateDaliObject();
 
   /**
    * Create Dali ObjectTemplate
@@ -150,9 +177,8 @@ private:
   GarbageCollector mGarbageCollector;                           ///< DALi garbage collector
   ModuleLoader mModuleLoader;                                   ///< Module loader
   v8::Persistent<v8::Context> mContext;                         ///< A sandboxed execution context with its own set of built-in objects and functions.
-  v8::Persistent<v8::ObjectTemplate> mGlobalObjectTemplate;     ///< Global object template for storing things like dali global object
   v8::Isolate* mIsolate;                                        ///< represents an isolated instance of the V8 engine.
-
+  RunMode mRunMode;
 };
 
 
index d475c90..12ad13c 100644 (file)
@@ -29,7 +29,6 @@ namespace V8Plugin
 
 ModuleLoader::ModuleLoader()
 {
-
 }
 
 ModuleLoader::~ModuleLoader()
@@ -311,9 +310,7 @@ bool ModuleLoader::ExecuteScriptFromFile( v8::Isolate* isolate,
  * @for ModuleLoader
  *
  */
-void ModuleLoader::Require(const v8::FunctionCallbackInfo< v8::Value >& args,
-
-                           v8::Persistent<v8::ObjectTemplate>& globalObjectTemplate )
+void ModuleLoader::Require(const v8::FunctionCallbackInfo< v8::Value >& args )
 {
   v8::Isolate* isolate = args.GetIsolate();
   v8::HandleScope handleScope( isolate );
@@ -393,6 +390,12 @@ void ModuleLoader::Require(const v8::FunctionCallbackInfo< v8::Value >& args,
   args.GetReturnValue().Set( moduleExports );
 
 }
+
+void ModuleLoader::StorePreBuiltModule( v8::Isolate* isolate, v8::Local<v8::Object>& exportObject, const std::string& name )
+{
+  StoreModule( "", name, name, isolate, exportObject );
+}
+
 void ModuleLoader::StoreScriptInfo( const std::string& sourceFileName )
 {
   V8Utils::GetFileDirectory( sourceFileName, mCurrentScriptPath);
index 085f33f..001f83e 100644 (file)
@@ -64,18 +64,21 @@ class ModuleLoader
 public:
 
   /**
-   * Constructor
+   * @brief Constructor
+   * @param[in] isolate v8 isolate
+   * @param[in] daliObject dali exports object, used when developer does require('dali');
    */
   ModuleLoader();
 
   /**
-   * non virtual destructor, not intended as a base class
+   * @brief non virtual destructor, not intended as a base class
    */
   ~ModuleLoader();
 
 
   /**
-   * Execute a script from a file
+   * @brief Execute a script from a file
+   * @param[in] isolate v8 isolate
    * @param[in] fileName file name
    * @return true on success, false on failure
    *
@@ -84,7 +87,8 @@ public:
 
 
   /**
-   * Execute a script
+   * @brief Execute a script
+   * @param[in] isolate v8 isolate
    * @param[in] sourceCode source code to run
    * @param[in] sourceFileName source file name
    * @return true on success, false on failure
@@ -95,9 +99,21 @@ public:
 
 
   /**
-   * Implements JavaScript Require functionality
+   * @brief Implements JavaScript Require functionality
+   * @param[in] args arguments passed to require. The return value is set using   args.GetReturnValue().Set(
    */
-  void Require(const v8::FunctionCallbackInfo< v8::Value >& args, v8::Persistent<v8::ObjectTemplate>& globalObjectTemplate );
+  void Require( const v8::FunctionCallbackInfo< v8::Value >& args );
+
+  /**
+   * @brief
+   * Stores a pre compiled object as a module.
+   * Currently used for storing the Dali object, so the developer can
+   * perform  var dali = require('dali');
+   * @param[in] isolate v8 isolate
+   * @param[in] exportObject export object
+   * @param[in] name module name, used for the require('name') lookup
+   */
+  void StorePreBuiltModule( v8::Isolate* isolate, v8::Local<v8::Object>& exportObject, const std::string& name );
 
 private:
 
@@ -111,13 +127,13 @@ private:
                      const std::string& sourceFileName );
 
   /**
-   * Store information about the current script
+   * @brief Store information about the current script
    * @param[in] sourceFileName source file name
    */
   void StoreScriptInfo( const std::string& sourceFileName );
 
   /**
-   * Store module information
+   * @brief Store module information
    * @param[in] sourceFileName source file name
    * @return module object
    */
@@ -128,7 +144,7 @@ private:
                     v8::Local<v8::Object>& moduleExportsObject );
 
   /**
-   * Find a module
+   * @brief Find a module
    * @param[in] moduleName module name
    * @return module
    */
index d9fbc7e..697b9dd 100644 (file)
@@ -64,7 +64,7 @@ void Log(const v8::FunctionCallbackInfo< v8::Value >& args)
       std::cout << " ";
     }
     v8::String::Utf8Value utf8_value( args[i] );
-    std::cout << *utf8_value;
+    std::cout << *utf8_value << "\n";
   }
 }
 
@@ -85,6 +85,7 @@ void LogError(const v8::FunctionCallbackInfo< v8::Value >& args)
     }
     v8::String::Utf8Value utf8_value( args[i] );
     output += *utf8_value;
+    output +="\n";
   }
   DALI_LOG_ERROR_NOFN( "JavaScript: %s",output.c_str() );
 }