Browse Source

amber-attic in its own repo

Herbert Vojčík 9 years ago
commit
4e9e4bd625
23 changed files with 9758 additions and 0 deletions
  1. 7 0
      .gitignore
  2. 68 0
      Gruntfile.js
  3. 22 0
      LICENSE-MIT
  4. 17 0
      README.md
  5. 39 0
      bower.json
  6. 10 0
      codemirror.amd.json
  7. 10 0
      deploy.js
  8. 8 0
      devel.js
  9. 23 0
      index.html
  10. 10 0
      jquery-ui.amd.json
  11. 18 0
      local.amd.json
  12. 37 0
      package.json
  13. 546 0
      resources/amber.css
  14. BIN
      resources/off.amber.png
  15. BIN
      resources/offHover.amber.png
  16. BIN
      resources/sprite.amber.png
  17. BIN
      resources/tinylogo.amber.png
  18. 489 0
      src/Benchfib.js
  19. 124 0
      src/Benchfib.st
  20. 195 0
      src/Examples.js
  21. 55 0
      src/Examples.st
  22. 5683 0
      src/IDE.js
  23. 2397 0
      src/IDE.st

+ 7 - 0
.gitignore

@@ -0,0 +1,7 @@
+/node_modules/
+/bower_components/
+
+/test_runner.js
+
+/config.js
+/the.js

+ 68 - 0
Gruntfile.js

@@ -0,0 +1,68 @@
+'use strict';
+
+module.exports = function (grunt) {
+    var path = require('path');
+
+    // These plugins provide necessary tasks.
+    grunt.loadNpmTasks('grunt-contrib-requirejs');
+    grunt.loadNpmTasks('amber-dev');
+
+    // Default task.
+    grunt.registerTask('default', ['amberc:all']);
+    grunt.registerTask('devel', ['amdconfig:app', 'requirejs:devel']);
+    grunt.registerTask('deploy', ['amdconfig:app', 'requirejs:deploy']);
+
+    // Project configuration.
+    grunt.initConfig({
+        // Metadata.
+        // pkg: grunt.file.readJSON(''),
+        banner: '/*! <%= pkg.title || pkg.name %> - v<%= pkg.version %> - ' +
+            '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
+            '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
+            '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
+            ' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
+        // task configuration
+        amberc: {
+            options: {
+                amber_dir: path.join(__dirname, "bower_components", "amber"),
+                library_dirs: ['src'],
+                closure_jar: ''
+            },
+            all: {
+                src: [
+                    'src/Benchfib.st', 'src/Examples.st', 'src/IDE.st' // list all sources in dependency order
+                    // list all tests in dependency order
+                ],
+                amd_namespace: 'amber-attic',
+                libraries: ['Web']
+            }
+        },
+
+        amdconfig: {app: {dest: 'config.js'}},
+
+        requirejs: {
+            deploy: {options: {
+                mainConfigFile: "config.js",
+                onBuildWrite: function (moduleName, path, contents) {
+                    return moduleName === "config" ? contents + "\nrequire.config({map:{'*':{app:'deploy'}}});" : contents;
+                },
+                pragmas: {
+                    excludeIdeData: true,
+                    excludeDebugContexts: true
+                },
+                include: ['config', 'node_modules/requirejs/require', 'deploy'],
+                out: "the.js"
+            }},
+            devel: {options: {
+                mainConfigFile: "config.js",
+                onBuildWrite: function (moduleName, path, contents) {
+                    return moduleName === "config" ? contents + "\nrequire.config({map:{'*':{app:'devel'}}});" : contents;
+                },
+                include: ['config', 'node_modules/requirejs/require'],
+                out: "the.js"
+            }}
+        }
+
+    });
+
+};

+ 22 - 0
LICENSE-MIT

@@ -0,0 +1,22 @@
+Copyright (c) 2015 Herbert Vojčík
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.

+ 17 - 0
README.md

@@ -0,0 +1,17 @@
+# Amber legacy items
+
+Legacy IDE and a few other old non-core packages
+
+## Getting Started
+
+To bring project alive (for example after `git clone`):
+
+```sh
+npm install
+bower install
+grunt devel
+```
+
+Developing the project (after brought alive):
+ 
+Start server with `amber serve` and go to `http://localhost:4000/` in your browser and follow the instructions

+ 39 - 0
bower.json

@@ -0,0 +1,39 @@
+{
+    "name": "amber-attic",
+    "description": "Legacy IDE and a few other old non-core packages",
+    "version": "0.1.0",
+    "ignore": [
+        "**/.*",
+        "node_modules",
+        "bower_components",
+        "/test_runner.js",
+        "/config.js",
+        "/the.js",
+        "test",
+        "tests"
+    ],
+    "authors": [
+        {
+            "name": "Herbert Vojčík",
+            "email": "herby@mailbox.sk"
+        }
+    ],
+    "homepage": "",
+    "keywords": [
+        "Amber",
+        "Smalltalk"
+    ],
+    "license": [
+        "MIT"
+    ],
+    "private": false,
+    "dependencies": {
+        "amber": "^0.14.0",
+        "jquery-ui": ">=1.9.2",
+        "codemirror": "^4.7.0"
+    },
+    "devDependencies": {
+        "amber-ide-starter-dialog": "^0.1.0",
+        "helios": "^0.3.2"
+    }
+}

+ 10 - 0
codemirror.amd.json

@@ -0,0 +1,10 @@
+{
+    "paths": {
+        "codemirror": "."
+    },
+    "shim": {
+        "codemirror/lib/codemirror": {
+            "deps": [ "css!codemirror/lib/codemirror" ]
+        }
+    }
+}

+ 10 - 0
deploy.js

@@ -0,0 +1,10 @@
+define([
+    'amber/deploy',
+    // --- packages to be deployed begin here ---
+    'amber-attic/Benchfib',
+    'amber-attic/Examples',
+    'amber-attic/IDE'
+    // --- packages to be deployed end here ---
+], function (amber) {
+    return amber;
+});

+ 8 - 0
devel.js

@@ -0,0 +1,8 @@
+define([
+    'amber/devel',
+    './deploy'
+    // --- packages used only during development begin here ---
+    // --- packages used only during development end here ---
+], function (amber) {
+    return amber;
+});

+ 23 - 0
index.html

@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html>
+
+  <head>
+    <title>Amber legacy items</title>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8" />
+    <meta name="author" content="Herbert Vojčík" />
+    <script type='text/javascript' src='the.js'></script>
+  </head>
+
+  <body>
+  <script type='text/javascript'>
+      require(['app'], function (amber) {
+          amber.initialize({
+            //used for all new packages in IDE
+            'transport.defaultAmdNamespace': "amber-attic"
+          });
+          require(["amber-ide-starter-dialog"], function (dlg) { dlg.start(); });
+      });
+  </script>
+  </body>
+
+</html>

+ 10 - 0
jquery-ui.amd.json

@@ -0,0 +1,10 @@
+{
+    "paths": {
+        "jquery-ui": ["jquery-ui", "ui/jquery-ui"]
+    },
+    "shim": {
+        "jquery-ui": {
+            "deps": [ "jquery" ]
+        }
+    }
+}

+ 18 - 0
local.amd.json

@@ -0,0 +1,18 @@
+{
+    "paths": {
+        "amber-attic": "src",
+        "amber-attic/resources": "resources"
+    },
+    "shim": {
+        "amber-attic/IDE": [
+            "codemirror/lib/codemirror",
+            "codemirror/mode/smalltalk/smalltalk",
+            "codemirror/addon/hint/show-hint",
+            "css!codemirror/theme/ambiance",
+            "css!codemirror/lib/codemirror",
+            "css!codemirror/addon/hint/show-hint",
+            "jquery-ui",
+            "css!./resources/amber"
+        ]
+    }
+}

+ 37 - 0
package.json

@@ -0,0 +1,37 @@
+{
+  "name": "amber-attic",
+  "title": "Amber legacy items",
+  "description": "Legacy IDE and a few other old non-core packages",
+  "version": "0.1.0",
+  "homepage": "",
+  "author": {
+    "name": "Herbert Vojčík",
+    "email": "herby@mailbox.sk"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git://guthub.com/amber-smalltalk/amber-attic.git"
+  },
+  "licenses": [
+    {
+      "type": "MIT",
+      "url": "/blob/master/LICENSE-MIT"
+    }
+  ],
+  "engines": {
+    "node": ">= 0.8.0"
+  },
+  "scripts": {
+    "test": "grunt test"
+  },
+  "devDependencies": {
+    "amber-dev": "^0.3.0",
+    "grunt": "^0.4.5",
+    "grunt-contrib-requirejs": "^0.4.4",
+    "requirejs": "^2.1.15"
+  },
+  "keywords": [
+    "Amber",
+    "Smalltalk"
+  ]
+}

+ 546 - 0
resources/amber.css

@@ -0,0 +1,546 @@
+body.amberBody {
+    margin-bottom: 350px;
+}
+
+#amberTabs, #amber .amber_tabs {
+    margin: 0;
+    padding: 0;
+    background: url("sprite.amber.png") #DBD9C9 0 -27px;
+    height: 22px;
+    width: 100%;
+    list-style: none;
+    font-weight: bold;
+}
+
+#amberTabs li, #amber .amber_tabs li {
+    padding: 0 1px;
+    cursor: pointer;
+    color: #565656;
+	max-width: 200px;
+	float:left;
+}
+#amber li {
+	line-height: 14px;
+
+}
+#amber .ltab, #amber .rtab, #amber .mtab {
+    height: 22px;
+    float: left;
+}
+
+#amber .ltab, #amber .rtab {
+    width: 8px;
+}
+
+#amber .rtab {
+    margin-right: 1px;
+}
+
+#amber .mtab {
+    line-height: 20px;
+}
+
+#amberTabs li:hover .ltab,
+#amber .amber_tabs li:hover .ltab {
+    background: url("sprite.amber.png") -16px -96px;
+}
+
+#amberTabs li:hover .mtab,
+#amber .amber_tabs li:hover .mtab {
+    background: url("sprite.amber.png") 0 -73px;
+}
+
+#amberTabs li:hover .rtab,
+#amber .amber_tabs li:hover .rtab {
+    background: url("sprite.amber.png") -24px -96px;
+}
+
+#amberTabs li.selected,
+#amber .amber_tabs li.selected {
+    color: #111;
+}
+
+#amberTabs li.selected .ltab,
+#amber .amber_tabs li.selected .ltab {
+    background: url("sprite.amber.png") 0px -96px;
+}
+
+#amberTabs li.selected .mtab,
+#amber .amber_tabs li.selected .mtab {
+    background: url("sprite.amber.png") 0 -50px;
+}
+
+#amberTabs li.selected .rtab,
+#amber .amber_tabs li.selected .rtab {
+    background: url("sprite.amber.png") -8px -96px;
+}
+
+#amberTabs li .close {
+    margin-right: 5px;
+    color: #aaa;
+}
+
+#amber {
+       position: fixed;
+       bottom: 0;
+       left: 0;
+       right: 0;
+       height: 350px;
+       z-index: 1000;
+}
+
+#amber, #amber button, #amber input, #amber select {
+       font-family: Lucida Grande, Tahoma, sans-serif;
+       font-size: 11px;
+}
+
+#amber #logo {
+    position: absolute;
+    top: 3px;
+    left: 8px;
+    width: 22px;
+    height: 20px;
+    background: url("tinylogo.amber.png") top left no-repeat;
+}
+
+#amber #amber_toolbar {
+    height: 27px;
+    background: url("sprite.amber.png") 0 0;
+}
+
+#amber #amber_toolbar input {
+    margin-left: 50px;
+    width: 250px;
+    margin-top: 5px;
+}
+
+#amber #amber_toolbar #amber_close {
+    position: absolute;
+    right: 4px;
+    top: 6px;
+    width: 16px;
+    height: 16px;
+    background: url('off.amber.png');
+    cursor: pointer;
+}
+
+#amber #amber_toolbar #amber_close:hover {
+    background: url('offHover.amber.png');
+}
+
+
+#amber .ui-resizable-handle {
+    background-color: transparent;
+    top: 0;
+    cursor: row-resize;
+    height: 5px;
+    left: 0;
+    position: absolute;
+    right: 0;
+    width: auto !important;
+}
+
+.amberTool {
+    width: 100%;
+    color: #333;
+    line-height: 1.3em;
+    padding: 0;
+    margin: 0;
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    top: 49px;
+    z-index: 1000;
+    background: white;
+}
+
+.amberTool .amber_box {
+    width: 100%;
+    margin: 0;
+    position: absolute;
+    top: 0;
+    bottom: 27px;
+}
+
+.amberTool .amber_buttons {
+    position: absolute;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    height: 27px;
+    line-height: 27px;
+    background: url("sprite.amber.png") 0 0 repeat;
+}
+
+.amberTool .amber_buttons .right {
+    float: right;
+}
+
+.amberTool .important {
+    font-weight: bold;
+}
+
+
+.amberTool button {
+    border: 1px solid transparent;
+    background: transparent;
+    padding: 2px 4px;
+    margin-left: 4px;
+    cursor: pointer;
+}
+
+.amberTool button:hover {
+    border-top: 1px solid #fff;
+    border-left: 1px solid #fff;
+    border-right: 1px solid #bbb;
+    border-bottom: 1px solid #bbb;
+}
+
+.amberTool  button:active {
+    border-top: 1px solid #bbb;
+    border-left: 1px solid #bbb;
+    border-right: 1px solid #fff;
+    border-bottom: 1px solid #fff;
+    background: #ddd;
+}
+
+.amberTool select, #amber input {
+    border-top: 1px solid #bbb;
+    border-left: 1px solid #bbb;
+    border-right: 1px solid #fff;
+    border-bottom: 1px solid #fff;
+    background: #fff;
+    display: inline;
+    margin-top: 0;
+    margin-bottom: 0;
+    padding-top: 0;
+    padding-bottom: 0;
+    height: 14px;
+    line-height: normal;
+    box-shadow: none;
+    outline: none;
+    vertical-align:baseline;
+}
+.amberTool select {
+    height:18px;
+    width: auto;
+}
+
+
+
+
+.amberTool li {
+    margin: 0;
+    padding: 0;
+}
+    
+.amberTool .source {
+    height: 100%;
+}
+
+.amberTool textarea,
+.amberTool input {
+    border: 0 none;
+    font-family:  "DejaVu Sans", Helvetica, sans-serif;
+    line-height: 1.3em;
+    font-size: 11px;
+    position: relative;
+    padding: 0;
+}
+
+.amberTool .CodeMirror {
+    border: 0 none;
+    font-family:  "DejaVu Sans", Helvetica, sans-serif;
+    font-size: 11px;
+    line-height: 1.3em;
+    height: 100%;
+    background: white;
+}
+
+.amberTool .CodeMirror-scroll {
+    height: 100%;
+}
+
+.amberTool .CodeMirror-scroll pre {
+    font-family: "DejaVu Sans", Helvetica, sans-serif;
+}
+
+.amberTool .amber_clear {
+    clear: both;
+}
+
+.amberTool .amber_transcript,
+.amberTool .amber_workspace {
+    width: 100%;
+    height: 100%;
+}
+
+.amberTool .amber_packagesButtons {
+    position: absolute;
+    top: 149px;
+    left: 0;
+    z-index: 1;
+}
+
+.amberTool .amber_column {
+    width: 25%;
+    padding: 0;
+    margin: 0;
+    float: left;
+    outline: 1px solid #aaa;
+    border: 0 none;
+    height: 150px;
+    overflow-y: auto;
+    background: #fff;
+    color: #111;
+    position: absolute;
+    top: 0;
+}
+
+.amberTool .amber_column.classes {
+    left: 25%
+}
+
+.amberTool .amber_column.classes ul {
+    margin-left: 0;
+}
+
+.amberTool .amber_column.classes ul li {
+    padding-left: 10px;
+    margin-left: 0;
+}
+
+.amberTool .amber_column.protocols {
+    left: 50%
+}
+
+.amberTool .amber_column.methods {
+    left: 75%
+}
+
+.amberTool .amber_column li {
+    list-style-type: none;
+    padding-left: 5px;
+    cursor: pointer;
+    color: #111;
+    font-weight: bold;
+}
+
+.amberTool .amber_column li.selected {
+	background: #c5c5c5;
+	color: #222;
+}
+
+.amberTool .amber_column li:hover {
+    background: #08c;
+    color: white;
+}
+
+#amber .amberTool .amber_tabs {
+    top: 150px;
+    position: absolute;
+}
+
+#amber .amberTool .amber_tabs.amber_browser {
+    padding-left: 25%;
+}
+
+.amberTool .amber_sourceCode {
+    position: absolute;
+    top: 172px;
+    bottom: 0;
+    left: 0;
+    right: 0;
+}
+
+.amberTool .amber_sourceCode textarea.source {
+    width: 100%;
+    height: 100%;
+}
+
+/* Debugger & inspector */
+
+.amberTool .amber_box .label {
+	width: 100%;
+	font-weight: bold;
+	text-align: center;
+	position: absolute;
+	line-height: 1.5em;
+	font-size: 16px;
+	color: red;
+	background: url("sprite.amber.png") top left repeat;
+	height: 27px;
+}
+
+.amberTool .amber_box .amber_column.debugger {
+    top: 178px;
+}
+
+.amberTool .amber_box .amber_column.debugger.contexts {
+    top: 27px;
+    width: 100%;
+}
+
+.amberTool .amber_sourceCode.debugger {
+    width: 60%;
+    top: 178px;
+}
+
+.amberTool .amber_box .amber_column.debugger.variables {
+    width: 10%;
+    left: 60%;
+    bottom: 0;
+    position: absolute;
+    height: auto;
+}
+
+.amberTool .amber_box .amber_column.debugger.inspector {
+    width: 30%;
+    left: 70%;
+    bottom: 0;
+    position: absolute;
+    height: auto;
+}
+
+.amberTool .amber_button.debugger.inspect {
+    position: absolute;
+    left: 60%;
+}
+
+.amberTool .amber_column.value {
+    left: 25%;
+    width: 75%;
+}
+
+.amberTool .amber_buttons.inspector {
+    position: absolute;
+    top: 150px;
+}
+
+
+/* ReferencesBrowser */
+
+.amberTool .amber_box .implementors {
+	width: 100%
+}
+
+.amberTool .amber_box .amber_column.implementors,
+.amberTool .amber_box .amber_column.senders,
+.amberTool .amber_box .amber_column.referenced_classes,
+.amberTool .amber_box .amber_column.matches {
+	top: 20px;
+	height: auto;
+	bottom: 0;
+	width: 25%;
+}
+
+.amberTool .amber_box .amber_column.senders {
+	left: 25%
+}
+
+.amberTool .amber_box .amber_column.referenced_classes {
+        left: 50%
+}
+
+.amberTool .amber_box .amber_column.matches {
+        left: 75%
+}
+
+.amberTool .amber_box .amber_column.implementors .column_label, 
+.amberTool .amber_box .amber_column.senders .column_label,
+.amberTool .amber_box .amber_column.referenced_classes .column_label,
+.amberTool .amber_box .amber_column.matches .column_label {
+	background: #dbdbdb
+}
+
+.amberTool .amber_box .amber_column.implementors .column_label:hover,
+.amberTool .amber_box .amber_column.senders .column_label:hover,
+.amberTool .amber_box .amber_column.referenced_classes .column_label:hover,
+.amberTool .amber_box .amber_column.matches .column_label:hover {
+	font-weight: bold;
+	color: #000;
+	cursor: default
+}
+
+
+.amberTool .classes .commented {
+		color: #33337F;
+}
+
+
+/* SUnit TestRunner  */
+
+.amberTool .amber_column.sunit.packages,
+.amberTool .amber_column.sunit.classes {
+	height: 100%
+}
+
+.amberTool .amber_column.sunit.classes li.all,
+.amberTool .amber_column.sunit.categories li.all {
+	background: #e3e3e3;
+	font-weight: bold
+}
+
+.amberTool .amber_column.sunit.classes li.all:hover ,
+.amberTool .amber_column.sunit.categories li.all:hover {
+	background: #0088CC;
+	font-weight: bold
+}
+
+.amberTool .sunit.status {
+	position: absolute;
+	left: 50%;
+	width: 50%;
+	outline: 1px solid #aaa;
+	background: white;
+	height: 40px
+}
+
+
+.amberTool .sunit.status.success {
+	background: #43d443;
+}
+
+
+.amberTool .sunit.status.failure {
+	background: #ecd443;
+}
+
+
+.amberTool .sunit.status.error {
+	background: #e56f3b;
+}
+
+.amberTool .progress_bar {
+	position: absolute;
+	left: 50%;
+	width: 50%;
+	top: 40px;
+	background: white;
+	outline: 1px solid #aaa;
+	min-height: 20px
+}
+
+.amberTool .progress_bar div {
+	background: #0088CC;
+	min-height: 20px;
+}
+
+.amberTool .amber_column.results.sunit {
+	left: 50%;
+	height: auto;
+        width: 50%;
+        top: 62px;
+        bottom: 0;
+}
+
+.amberTool .amber_column.sunit.results .errors {
+    color: red;
+}
+
+/*.amberTool .amber_column.sunit.results ul {padding: 0; margin: 0}*/
+
+/* Code mirror overrides */
+.CodeMirror pre {
+	line-height: 14px;
+}

BIN
resources/off.amber.png


BIN
resources/offHover.amber.png


BIN
resources/sprite.amber.png


BIN
resources/tinylogo.amber.png


+ 489 - 0
src/Benchfib.js

@@ -0,0 +1,489 @@
+define("amber-attic/Benchfib", ["amber/boot", "amber_core/Kernel-Objects"], function($boot){
+var $core=$boot.api,nil=$boot.nil,$recv=$boot.asReceiver,$globals=$boot.globals;
+$core.addPackage('Benchfib');
+$core.packages["Benchfib"].transport = {"type":"amd","amdNamespace":"amber-attic"};
+
+$core.addClass('Benchfib', $globals.Object, [], 'Benchfib');
+
+$core.addMethod(
+$core.method({
+selector: "main",
+protocol: 'not yet classified',
+fn: function (){
+var self=this;
+var result;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+result=(0)._tinyBenchmarks();
+$recv(console)._log_("0 tinyBenchmarks => ".__comma(result));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"main",{result:result},$globals.Benchfib.klass)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "main\x0a\x0a\x09| result |\x0a\x09result := 0 tinyBenchmarks.\x0a\x09console log: '0 tinyBenchmarks => ' , result",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["tinyBenchmarks", "log:", ","]
+}),
+$globals.Benchfib.klass);
+
+$core.addMethod(
+$core.method({
+selector: "benchFib",
+protocol: '*Benchfib',
+fn: function (){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $2,$5,$4,$3,$1;
+$2=self.__lt((2));
+if($core.assert($2)){
+$1=(1);
+} else {
+$5=self.__minus((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["-"]=1;
+//>>excludeEnd("ctx");
+$4=$recv($5)._benchFib();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["benchFib"]=1;
+//>>excludeEnd("ctx");
+$3=$recv($4).__plus($recv(self.__minus((2)))._benchFib());
+$1=$recv($3).__plus((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["+"]=1;
+//>>excludeEnd("ctx");
+};
+return $1;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"benchFib",{},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "benchFib\x0a\x09\x22Handy send-heavy benchmark\x22\x0a\x09\x22(result // seconds to run) = approx calls per second\x22\x0a\x09\x22\x09| r t |\x0a\x09\x09t := Time millisecondsToRun: [r := 26 benchFib].\x0a\x09\x09(r * 1000) // t\x22\x0a\x09\x22138000 on a Mac 8100/100\x22\x0a\x09^ self < 2\x0a\x09\x09ifTrue: [1]\x0a\x09\x09ifFalse: [(self-1) benchFib + (self-2) benchFib + 1]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["ifTrue:ifFalse:", "<", "+", "benchFib", "-"]
+}),
+$globals.Number);
+
+$core.addMethod(
+$core.method({
+selector: "benchmark",
+protocol: '*Benchfib',
+fn: function (){
+var self=this;
+var size,flags,prime,k,count;
+function $Array(){return $globals.Array||(typeof Array=="undefined"?nil:Array)}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2;
+size=(8190);
+(1)._to_do_(self,(function(iter){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+count=(0);
+count;
+flags=$recv($Array())._new();
+flags;
+$recv(size)._timesRepeat_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx3) {
+//>>excludeEnd("ctx");
+return $recv(flags)._add_(true);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)});
+//>>excludeEnd("ctx");
+}));
+return (1)._to_do_(size,(function(i){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx3) {
+//>>excludeEnd("ctx");
+$1=$recv(flags)._at_(i);
+if($core.assert($1)){
+prime=$recv(i).__plus((1));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx3.sendIdx["+"]=1;
+//>>excludeEnd("ctx");
+prime;
+k=$recv(i).__plus(prime);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx3.sendIdx["+"]=2;
+//>>excludeEnd("ctx");
+k;
+$recv((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx4) {
+//>>excludeEnd("ctx");
+return $recv(k).__lt_eq(size);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx4) {$ctx4.fillBlock({},$ctx3,5)});
+//>>excludeEnd("ctx");
+}))._whileTrue_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx4) {
+//>>excludeEnd("ctx");
+$recv(flags)._at_put_(k,false);
+k=$recv(k).__plus(prime);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx4.sendIdx["+"]=3;
+//>>excludeEnd("ctx");
+return k;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx4) {$ctx4.fillBlock({},$ctx3,6)});
+//>>excludeEnd("ctx");
+}));
+count=$recv(count).__plus((1));
+return count;
+};
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx3) {$ctx3.fillBlock({i:i},$ctx2,3)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({iter:iter},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["to:do:"]=1;
+//>>excludeEnd("ctx");
+$2=count;
+return $2;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"benchmark",{size:size,flags:flags,prime:prime,k:k,count:count},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "benchmark\x0a\x09\x22Handy bytecode-heavy benchmark\x22\x0a\x09\x22(500000 // time to run) = approx bytecodes per second\x22\x0a\x09\x225000000 // (Time millisecondsToRun: [10 benchmark]) * 1000\x22\x0a\x09\x223059000 on a Mac 8100/100\x22\x0a\x09| size flags prime k count |\x0a\x09size := 8190.\x0a\x091 to: self do:\x0a\x09\x09[:iter |\x0a\x09\x09count := 0.\x0a\x09\x09flags := Array new.\x0a\x09\x09size timesRepeat: [ flags add: true].\x0a\x09\x091 to: size do:\x0a\x09\x09\x09[:i | (flags at: i) ifTrue:\x0a\x09\x09\x09\x09[prime := i+1.\x0a\x09\x09\x09\x09k := i + prime.\x0a\x09\x09\x09\x09[k <= size] whileTrue:\x0a\x09\x09\x09\x09\x09[flags at: k put: false.\x0a\x09\x09\x09\x09\x09k := k + prime].\x0a\x09\x09\x09\x09count := count + 1]]].\x0a\x09^ count",
+referencedClasses: ["Array"],
+//>>excludeEnd("ide");
+messageSends: ["to:do:", "new", "timesRepeat:", "add:", "ifTrue:", "at:", "+", "whileTrue:", "<=", "at:put:"]
+}),
+$globals.Number);
+
+$core.addMethod(
+$core.method({
+selector: "jsbenchFib",
+protocol: '*Benchfib',
+fn: function (){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+if (this < 2) {
+return 1;
+} else {
+return (this-1)._jsbenchFib() + (this-2)._jsbenchFib() + 1;};
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"jsbenchFib",{},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "jsbenchFib\x0a\x0a\x09<if (this < 2) {\x0areturn 1;\x0a} else {\x0areturn (this-1)._jsbenchFib() + (this-2)._jsbenchFib() + 1;}>",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.Number);
+
+$core.addMethod(
+$core.method({
+selector: "jsbenchmark",
+protocol: '*Benchfib',
+fn: function (){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+
+var size = 8190;
+var count;
+for (var z=0;z<this;z++) {
+	count = 0;
+	var flags = new Array();
+	for (var p=0; p<size; p++) {
+	flags[p] = true;
+	}
+	for (var i=1;i<=size;i++) {
+		if (flags[i-1]) {
+			var prime = i+1;
+			var k = i + prime;
+			while (k <= size) {
+				flags[k-1] = false;
+				k = k + prime;
+			}
+			count = count + 1;
+		}
+	}
+}
+return count;
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"jsbenchmark",{},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "jsbenchmark\x0a\x0a<\x0avar size = 8190;\x0avar count;\x0afor (var z=0;z<this;z++) {\x0a\x09count = 0;\x0a\x09var flags = new Array();\x0a\x09for (var p=0; p<size; p++) {\x0a\x09flags[p] = true;\x0a\x09}\x0a\x09for (var i=1;i<=size;i++) {\x0a\x09\x09if (flags[i-1]) {\x0a\x09\x09\x09var prime = i+1;\x0a\x09\x09\x09var k = i + prime;\x0a\x09\x09\x09while (k <= size) {\x0a\x09\x09\x09\x09flags[k-1] = false;\x0a\x09\x09\x09\x09k = k + prime;\x0a\x09\x09\x09}\x0a\x09\x09\x09count = count + 1;\x0a\x09\x09}\x0a\x09}\x0a}\x0areturn count>",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: []
+}),
+$globals.Number);
+
+$core.addMethod(
+$core.method({
+selector: "jstinyBenchmarks",
+protocol: '*Benchfib',
+fn: function (){
+var self=this;
+var t1,t2,r,n1,n2;
+function $Date(){return $globals.Date||(typeof Date=="undefined"?nil:Date)}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $7,$6,$5,$4,$3,$2,$1;
+n1=(1);
+$recv((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+t1=$recv($Date())._millisecondsToRun_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx3) {
+//>>excludeEnd("ctx");
+return $recv(n1)._jsbenchmark();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx2.sendIdx["millisecondsToRun:"]=1;
+//>>excludeEnd("ctx");
+t1;
+return $recv(t1).__lt((1000));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx2.sendIdx["<"]=1;
+//>>excludeEnd("ctx");
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}))._whileTrue_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+n1=$recv(n1).__star((2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx2.sendIdx["*"]=1;
+//>>excludeEnd("ctx");
+return n1;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["whileTrue:"]=1;
+//>>excludeEnd("ctx");
+n2=(28);
+$recv((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+t2=$recv($Date())._millisecondsToRun_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx3) {
+//>>excludeEnd("ctx");
+r=$recv(n2)._jsbenchFib();
+return r;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,5)});
+//>>excludeEnd("ctx");
+}));
+t2;
+return $recv(t2).__lt((1000));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,4)});
+//>>excludeEnd("ctx");
+}))._whileTrue_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+n2=$recv(n2).__plus((1));
+return n2;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,6)});
+//>>excludeEnd("ctx");
+}));
+$7=$recv(n1).__star((500000));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["*"]=3;
+//>>excludeEnd("ctx");
+$6=$recv($7).__star((1000));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["*"]=2;
+//>>excludeEnd("ctx");
+$5=$recv($6).__slash(t1);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["/"]=1;
+//>>excludeEnd("ctx");
+$4=$recv($5)._printString();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["printString"]=1;
+//>>excludeEnd("ctx");
+$3=$recv($4).__comma(" bytecodes/sec; ");
+$2=$recv($3).__comma($recv($recv($recv(r).__star((1000))).__slash(t2))._printString());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx[","]=2;
+//>>excludeEnd("ctx");
+$1=$recv($2).__comma(" sends/sec");
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx[","]=1;
+//>>excludeEnd("ctx");
+return $1;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"jstinyBenchmarks",{t1:t1,t2:t2,r:r,n1:n1,n2:n2},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "jstinyBenchmarks\x0a\x09\x220 jstinyBenchmarks\x22\x0a\x0a\x09| t1 t2 r n1 n2 |\x0a\x09n1 := 1.\x0a\x09[t1 := Date millisecondsToRun: [n1 jsbenchmark].\x0a\x09t1 < 1000] whileTrue:[n1 := n1 * 2]. \x22Note: #benchmark's runtime is about O(n)\x22\x0a\x0a\x09n2 := 28.\x0a\x09[t2 := Date millisecondsToRun: [r := n2 jsbenchFib].\x0a\x09t2 < 1000] whileTrue:[n2 := n2 + 1].\x0a\x09\x22Note: #jsbenchFib's runtime is about O(k^n),\x0a\x09\x09where k is the golden number = (1 + 5 sqrt) / 2 = 1.618....\x22\x0a\x0a\x09^ ((n1 * 500000 * 1000) / t1) printString, ' bytecodes/sec; ',\x0a\x09\x09((r * 1000) / t2) printString, ' sends/sec'",
+referencedClasses: ["Date"],
+//>>excludeEnd("ide");
+messageSends: ["whileTrue:", "millisecondsToRun:", "jsbenchmark", "<", "*", "jsbenchFib", "+", ",", "printString", "/"]
+}),
+$globals.Number);
+
+$core.addMethod(
+$core.method({
+selector: "tinyBenchmarks",
+protocol: '*Benchfib',
+fn: function (){
+var self=this;
+var t1,t2,r,n1,n2;
+function $Date(){return $globals.Date||(typeof Date=="undefined"?nil:Date)}
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $7,$6,$5,$4,$3,$2,$1;
+n1=(1);
+$recv((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+t1=$recv($Date())._millisecondsToRun_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx3) {
+//>>excludeEnd("ctx");
+return $recv(n1)._benchmark();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,2)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx2.sendIdx["millisecondsToRun:"]=1;
+//>>excludeEnd("ctx");
+t1;
+return $recv(t1).__lt((1000));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx2.sendIdx["<"]=1;
+//>>excludeEnd("ctx");
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}))._whileTrue_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+n1=$recv(n1).__star((2));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx2.sendIdx["*"]=1;
+//>>excludeEnd("ctx");
+return n1;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,3)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["whileTrue:"]=1;
+//>>excludeEnd("ctx");
+n2=(16);
+$recv((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+t2=$recv($Date())._millisecondsToRun_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx3) {
+//>>excludeEnd("ctx");
+r=$recv(n2)._benchFib();
+return r;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx3) {$ctx3.fillBlock({},$ctx2,5)});
+//>>excludeEnd("ctx");
+}));
+t2;
+return $recv(t2).__lt((1000));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,4)});
+//>>excludeEnd("ctx");
+}))._whileTrue_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+n2=$recv(n2).__plus((1));
+return n2;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,6)});
+//>>excludeEnd("ctx");
+}));
+$7=$recv(n1).__star((500000));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["*"]=3;
+//>>excludeEnd("ctx");
+$6=$recv($7).__star((1000));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["*"]=2;
+//>>excludeEnd("ctx");
+$5=$recv($6).__slash(t1);
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["/"]=1;
+//>>excludeEnd("ctx");
+$4=$recv($5)._printString();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["printString"]=1;
+//>>excludeEnd("ctx");
+$3=$recv($4).__comma(" bytecodes/sec; ");
+$2=$recv($3).__comma($recv($recv($recv(r).__star((1000))).__slash(t2))._printString());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx[","]=2;
+//>>excludeEnd("ctx");
+$1=$recv($2).__comma(" sends/sec");
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx[","]=1;
+//>>excludeEnd("ctx");
+return $1;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"tinyBenchmarks",{t1:t1,t2:t2,r:r,n1:n1,n2:n2},$globals.Number)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "tinyBenchmarks\x0a\x09\x22Report the results of running the two tiny Squeak benchmarks.\x0a\x09ar 9/10/1999: Adjusted to run at least 1 sec to get more stable results\x22\x0a\x09\x220 tinyBenchmarks\x22\x0a\x09\x22On a 292 MHz G3 Mac: 22727272 bytecodes/sec; 984169 sends/sec\x22\x0a\x09\x22On a 400 MHz PII/Win98: 18028169 bytecodes/sec; 1081272 sends/sec\x22\x0a\x09| t1 t2 r n1 n2 |\x0a\x09n1 := 1.\x0a\x09[t1 := Date millisecondsToRun: [n1 benchmark].\x0a\x09t1 < 1000] whileTrue:[n1 := n1 * 2]. \x22Note: #benchmark's runtime is about O(n)\x22\x0a\x0a\x09n2 := 16.\x0a\x09[t2 := Date millisecondsToRun: [r := n2 benchFib].\x0a\x09t2 < 1000] whileTrue:[n2 := n2 + 1].\x0a\x09\x22Note: #benchFib's runtime is about O(k^n),\x0a\x09\x09where k is the golden number = (1 + 5 sqrt) / 2 = 1.618....\x22\x0a\x0a\x09^ ((n1 * 500000 * 1000) / t1) printString, ' bytecodes/sec; ',\x0a\x09\x09((r * 1000) / t2) printString, ' sends/sec'",
+referencedClasses: ["Date"],
+//>>excludeEnd("ide");
+messageSends: ["whileTrue:", "millisecondsToRun:", "benchmark", "<", "*", "benchFib", "+", ",", "printString", "/"]
+}),
+$globals.Number);
+
+});

+ 124 - 0
src/Benchfib.st

@@ -0,0 +1,124 @@
+Smalltalk createPackage: 'Benchfib'!
+Object subclass: #Benchfib
+	instanceVariableNames: ''
+	package: 'Benchfib'!
+
+!Benchfib class methodsFor: 'not yet classified'!
+
+main
+
+	| result |
+	result := 0 tinyBenchmarks.
+	console log: '0 tinyBenchmarks => ' , result
+! !
+
+!Number methodsFor: '*Benchfib'!
+
+benchFib
+	"Handy send-heavy benchmark"
+	"(result // seconds to run) = approx calls per second"
+	"	| r t |
+		t := Time millisecondsToRun: [r := 26 benchFib].
+		(r * 1000) // t"
+	"138000 on a Mac 8100/100"
+	^ self < 2
+		ifTrue: [1]
+		ifFalse: [(self-1) benchFib + (self-2) benchFib + 1]
+!
+
+benchmark
+	"Handy bytecode-heavy benchmark"
+	"(500000 // time to run) = approx bytecodes per second"
+	"5000000 // (Time millisecondsToRun: [10 benchmark]) * 1000"
+	"3059000 on a Mac 8100/100"
+	| size flags prime k count |
+	size := 8190.
+	1 to: self do:
+		[:iter |
+		count := 0.
+		flags := Array new.
+		size timesRepeat: [ flags add: true].
+		1 to: size do:
+			[:i | (flags at: i) ifTrue:
+				[prime := i+1.
+				k := i + prime.
+				[k <= size] whileTrue:
+					[flags at: k put: false.
+					k := k + prime].
+				count := count + 1]]].
+	^ count
+!
+
+jsbenchFib
+
+	<if (this < 2) {
+return 1;
+} else {
+return (this-1)._jsbenchFib() + (this-2)._jsbenchFib() + 1;}>
+!
+
+jsbenchmark
+
+<
+var size = 8190;
+var count;
+for (var z=0;z<this;z++) {
+	count = 0;
+	var flags = new Array();
+	for (var p=0; p<size; p++) {
+	flags[p] = true;
+	}
+	for (var i=1;i<=size;i++) {
+		if (flags[i-1]) {
+			var prime = i+1;
+			var k = i + prime;
+			while (k <= size) {
+				flags[k-1] = false;
+				k = k + prime;
+			}
+			count = count + 1;
+		}
+	}
+}
+return count>
+!
+
+jstinyBenchmarks
+	"0 jstinyBenchmarks"
+
+	| t1 t2 r n1 n2 |
+	n1 := 1.
+	[t1 := Date millisecondsToRun: [n1 jsbenchmark].
+	t1 < 1000] whileTrue:[n1 := n1 * 2]. "Note: #benchmark's runtime is about O(n)"
+
+	n2 := 28.
+	[t2 := Date millisecondsToRun: [r := n2 jsbenchFib].
+	t2 < 1000] whileTrue:[n2 := n2 + 1].
+	"Note: #jsbenchFib's runtime is about O(k^n),
+		where k is the golden number = (1 + 5 sqrt) / 2 = 1.618...."
+
+	^ ((n1 * 500000 * 1000) / t1) printString, ' bytecodes/sec; ',
+		((r * 1000) / t2) printString, ' sends/sec'
+!
+
+tinyBenchmarks
+	"Report the results of running the two tiny Squeak benchmarks.
+	ar 9/10/1999: Adjusted to run at least 1 sec to get more stable results"
+	"0 tinyBenchmarks"
+	"On a 292 MHz G3 Mac: 22727272 bytecodes/sec; 984169 sends/sec"
+	"On a 400 MHz PII/Win98: 18028169 bytecodes/sec; 1081272 sends/sec"
+	| t1 t2 r n1 n2 |
+	n1 := 1.
+	[t1 := Date millisecondsToRun: [n1 benchmark].
+	t1 < 1000] whileTrue:[n1 := n1 * 2]. "Note: #benchmark's runtime is about O(n)"
+
+	n2 := 16.
+	[t2 := Date millisecondsToRun: [r := n2 benchFib].
+	t2 < 1000] whileTrue:[n2 := n2 + 1].
+	"Note: #benchFib's runtime is about O(k^n),
+		where k is the golden number = (1 + 5 sqrt) / 2 = 1.618...."
+
+	^ ((n1 * 500000 * 1000) / t1) printString, ' bytecodes/sec; ',
+		((r * 1000) / t2) printString, ' sends/sec'
+! !
+

+ 195 - 0
src/Examples.js

@@ -0,0 +1,195 @@
+define("amber-attic/Examples", ["amber/boot", "amber_core/Web"], function($boot){
+var $core=$boot.api,nil=$boot.nil,$recv=$boot.asReceiver,$globals=$boot.globals;
+$core.addPackage('Examples');
+$core.packages["Examples"].transport = {"type":"amd","amdNamespace":"amber-attic"};
+
+$core.addClass('Counter', $globals.Widget, ['count', 'header'], 'Examples');
+//>>excludeStart("ide", pragmas.excludeIdeData);
+$globals.Counter.comment="This is a trivial Widget example mimicking the classic Counter example in Seaside.\x0aIn order to play with it, just evaluate the doit below in a workspace.\x0aThen take a look in the HTML document above the IDE.\x0a\x0a\x09\x09Counter tryExample";
+//>>excludeEnd("ide");
+$core.addMethod(
+$core.method({
+selector: "decrease",
+protocol: 'actions',
+fn: function (){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+self["@count"]=$recv(self["@count"]).__minus((1));
+$recv(self["@header"])._contents_((function(html){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $recv(html)._with_($recv(self["@count"])._asString());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({html:html},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"decrease",{},$globals.Counter)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "decrease\x0a\x09count := count - 1.\x0a\x09header contents: [ :html | html with: count asString ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["-", "contents:", "with:", "asString"]
+}),
+$globals.Counter);
+
+$core.addMethod(
+$core.method({
+selector: "increase",
+protocol: 'actions',
+fn: function (){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+self["@count"]=$recv(self["@count"]).__plus((1));
+$recv(self["@header"])._contents_((function(html){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return $recv(html)._with_($recv(self["@count"])._asString());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({html:html},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"increase",{},$globals.Counter)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "increase\x0a\x09count := count + 1.\x0a\x09header contents: [ :html | html with: count asString ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["+", "contents:", "with:", "asString"]
+}),
+$globals.Counter);
+
+$core.addMethod(
+$core.method({
+selector: "initialize",
+protocol: 'initialization',
+fn: function (){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+(
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = true, 
+//>>excludeEnd("ctx");
+$globals.Counter.superclass.fn.prototype._initialize.apply($recv(self), []));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.supercall = false;
+//>>excludeEnd("ctx");;
+self["@count"]=(0);
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"initialize",{},$globals.Counter)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "initialize\x0a\x09super initialize.\x0a\x09count := 0",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["initialize"]
+}),
+$globals.Counter);
+
+$core.addMethod(
+$core.method({
+selector: "renderOn:",
+protocol: 'rendering',
+fn: function (html){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+var $1,$2,$3,$4,$5,$6;
+$1=$recv(html)._h1();
+$recv($1)._with_($recv(self["@count"])._asString());
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["with:"]=1;
+//>>excludeEnd("ctx");
+$2=$recv($1)._yourself();
+self["@header"]=$2;
+$3=$recv(html)._button();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["button"]=1;
+//>>excludeEnd("ctx");
+$recv($3)._with_("++");
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["with:"]=2;
+//>>excludeEnd("ctx");
+$4=$recv($3)._onClick_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return self._increase();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,1)});
+//>>excludeEnd("ctx");
+}));
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+$ctx1.sendIdx["onClick:"]=1;
+//>>excludeEnd("ctx");
+$5=$recv(html)._button();
+$recv($5)._with_("--");
+$6=$recv($5)._onClick_((function(){
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx2) {
+//>>excludeEnd("ctx");
+return self._decrease();
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx2) {$ctx2.fillBlock({},$ctx1,2)});
+//>>excludeEnd("ctx");
+}));
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"renderOn:",{html:html},$globals.Counter)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: ["html"],
+source: "renderOn: html\x0a\x09header := html h1\x0a\x09\x09with: count asString;\x0a\x09\x09yourself.\x0a\x09html button\x0a\x09\x09with: '++';\x0a\x09\x09onClick: [ self increase ].\x0a\x09html button\x0a\x09\x09with: '--';\x0a\x09\x09onClick: [ self decrease ]",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["with:", "h1", "asString", "yourself", "button", "onClick:", "increase", "decrease"]
+}),
+$globals.Counter);
+
+
+$core.addMethod(
+$core.method({
+selector: "tryExample",
+protocol: 'example',
+fn: function (){
+var self=this;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+return $core.withContext(function($ctx1) {
+//>>excludeEnd("ctx");
+$recv(self._new())._appendToJQuery_("body"._asJQuery());
+return self;
+//>>excludeStart("ctx", pragmas.excludeDebugContexts);
+}, function($ctx1) {$ctx1.fill(self,"tryExample",{},$globals.Counter.klass)});
+//>>excludeEnd("ctx");
+},
+//>>excludeStart("ide", pragmas.excludeIdeData);
+args: [],
+source: "tryExample\x0a\x09\x22In order to play with the Counter, just select the\x0a\x09doit below and press the Do it button. Then take a\x0a\x09look in the HTML document above the IDE.\x22\x0a\x0a\x09\x22Counter tryExample\x22\x0a\x09\x09self new appendToJQuery: 'body' asJQuery",
+referencedClasses: [],
+//>>excludeEnd("ide");
+messageSends: ["appendToJQuery:", "new", "asJQuery"]
+}),
+$globals.Counter.klass);
+
+});

+ 55 - 0
src/Examples.st

@@ -0,0 +1,55 @@
+Smalltalk createPackage: 'Examples'!
+Widget subclass: #Counter
+	instanceVariableNames: 'count header'
+	package: 'Examples'!
+!Counter commentStamp!
+This is a trivial Widget example mimicking the classic Counter example in Seaside.
+In order to play with it, just evaluate the doit below in a workspace.
+Then take a look in the HTML document above the IDE.
+
+		Counter tryExample!
+
+!Counter methodsFor: 'actions'!
+
+decrease
+	count := count - 1.
+	header contents: [ :html | html with: count asString ]
+!
+
+increase
+	count := count + 1.
+	header contents: [ :html | html with: count asString ]
+! !
+
+!Counter methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+	count := 0
+! !
+
+!Counter methodsFor: 'rendering'!
+
+renderOn: html
+	header := html h1
+		with: count asString;
+		yourself.
+	html button
+		with: '++';
+		onClick: [ self increase ].
+	html button
+		with: '--';
+		onClick: [ self decrease ]
+! !
+
+!Counter class methodsFor: 'example'!
+
+tryExample
+	"In order to play with the Counter, just select the
+	doit below and press the Do it button. Then take a
+	look in the HTML document above the IDE."
+
+	"Counter tryExample"
+		self new appendToJQuery: 'body' asJQuery
+! !
+

File diff suppressed because it is too large
+ 5683 - 0
src/IDE.js


+ 2397 - 0
src/IDE.st

@@ -0,0 +1,2397 @@
+Smalltalk createPackage: 'IDE'!
+Widget subclass: #ClassesList
+	instanceVariableNames: 'browser ul nodes'
+	package: 'IDE'!
+
+!ClassesList methodsFor: 'accessing'!
+
+browser
+	^ browser
+!
+
+browser: aBrowser
+	browser := aBrowser
+!
+
+category
+	^ self browser selectedPackage
+!
+
+getNodes
+	| classes children others |
+	classes := self browser classes.
+	children := #().
+	others := #().
+	classes do: [ :each |
+		(classes includes: each superclass)
+			ifFalse: [ children add: each ]
+			ifTrue: [ others add: each ]].
+	^ children collect: [ :each |
+		ClassesListNode on: each browser: self browser classes: others level: 0 ]
+!
+
+nodes
+	nodes ifNil: [ nodes := self getNodes ].
+	^ nodes
+!
+
+resetNodes
+	nodes := nil
+! !
+
+!ClassesList methodsFor: 'rendering'!
+
+renderOn: html
+	ul := html ul
+		class: 'amber_column browser classes';
+		yourself.
+	self updateNodes
+!
+
+updateNodes
+	ul contents: [ :html |
+		self nodes do: [ :each |
+			each renderOn: html ]]
+! !
+
+!ClassesList class methodsFor: 'instance creation'!
+
+on: aBrowser
+	^ self new
+		browser: aBrowser;
+		yourself
+! !
+
+Widget subclass: #ClassesListNode
+	instanceVariableNames: 'browser theClass level nodes'
+	package: 'IDE'!
+
+!ClassesListNode methodsFor: 'accessing'!
+
+browser
+	^ browser
+!
+
+browser: aBrowser
+	browser := aBrowser
+!
+
+getNodesFrom: aCollection
+	| children others |
+	children := #().
+	others := #().
+	aCollection do: [ :each |
+		(each superclass = self theClass)
+			ifTrue: [ children add: each ]
+			ifFalse: [ others add: each ]].
+	nodes:= children collect: [ :each |
+		ClassesListNode on: each browser: self browser classes: others level: self level + 1 ]
+!
+
+label
+	| str |
+	str := String new writeStream.
+	self level timesRepeat: [
+		str nextPutAll: '&nbsp;&nbsp;&nbsp;&nbsp;' ].
+	str nextPutAll: self theClass name.
+	^ str contents
+!
+
+level
+	^ level
+!
+
+level: anInteger
+	level := anInteger
+!
+
+nodes
+	^ nodes
+!
+
+theClass
+	^ theClass
+!
+
+theClass: aClass
+	theClass := aClass
+! !
+
+!ClassesListNode methodsFor: 'rendering'!
+
+renderOn: html
+	| li cssClass |
+	cssClass := ''.
+	li := html li
+		onClick: [ self browser selectClass: self theClass ].
+	li asJQuery html: self label.
+
+	self browser selectedClass = self theClass ifTrue: [
+		cssClass := cssClass, ' selected' ].
+
+	self theClass comment isEmpty ifFalse: [
+		cssClass := cssClass, ' commented' ].
+
+	li class: cssClass.
+
+	self nodes do: [ :each |
+		each renderOn: html ]
+! !
+
+!ClassesListNode class methodsFor: 'instance creation'!
+
+on: aClass browser: aBrowser classes: aCollection level: anInteger
+	^ self new
+		theClass: aClass;
+		browser: aBrowser;
+		level: anInteger;
+		getNodesFrom: aCollection;
+		yourself
+! !
+
+Object subclass: #DebugErrorHandler
+	instanceVariableNames: ''
+	package: 'IDE'!
+
+!DebugErrorHandler methodsFor: 'error handling'!
+
+handleError: anError
+	[ Debugger new
+		error: anError;
+		open ] on: Error do: [ :error |
+			ConsoleErrorHandler new handleError: error ]
+! !
+
+!DebugErrorHandler class methodsFor: 'initialization'!
+
+initialize
+	ErrorHandler register: self new
+! !
+
+Widget subclass: #SourceArea
+	instanceVariableNames: 'editor div receiver onDoIt'
+	package: 'IDE'!
+
+!SourceArea methodsFor: 'accessing'!
+
+currentLine
+	^ editor getLine: (editor getCursor line)
+!
+
+currentLineOrSelection
+	^ editor somethingSelected
+	ifFalse: [ self currentLine ]
+	ifTrue: [ self selection ]
+!
+
+editor
+	^ editor
+!
+
+onDoIt
+	^ onDoIt
+!
+
+onDoIt: aBlock
+	onDoIt := aBlock
+!
+
+receiver
+	^ receiver ifNil: [ DoIt new ]
+!
+
+receiver: anObject
+	receiver := anObject
+!
+
+selection
+	^ editor getSelection
+!
+
+setEditorOn: aTextarea
+	<self['@editor'] = self._class()._codeMirror().fromTextArea(aTextarea, {
+		theme: 'ide.codeMirrorTheme'._settingValueIfAbsent_('default'),
+		mode: 'text/x-stsrc',
+		lineNumbers: true,
+		enterMode: 'flat',
+		indentWithTabs: true,
+		indentUnit: 4,
+		matchBrackets: true,
+		electricChars: false
+	})>
+!
+
+val
+	^ editor getValue
+!
+
+val: aString
+	editor setValue: aString
+! !
+
+!SourceArea methodsFor: 'actions'!
+
+clear
+	self val: ''
+!
+
+doIt
+	| result |
+	result := self eval: self currentLineOrSelection.
+	self onDoIt ifNotNil: [ self onDoIt value ].
+	^ result
+!
+
+eval: aString
+	| compiler |
+	compiler := Compiler new.
+	[ compiler parseExpression: aString ] on: Error do: [ :ex |
+		^ self alert: ex messageText ].
+	^ compiler evaluateExpression: aString on: self receiver
+!
+
+fileIn
+	Importer new import: self currentLineOrSelection readStream
+!
+
+focus
+	self editor focus.
+!
+
+handleKeyDown: anEvent
+	<if(anEvent.ctrlKey) {
+		if(anEvent.keyCode === 80) { //ctrl+p
+			self._printIt();
+			anEvent.preventDefault();
+			return false;
+		}
+		if(anEvent.keyCode === 68) { //ctrl+d
+			self._doIt();
+			anEvent.preventDefault();
+			return false;
+		}
+		if(anEvent.keyCode === 73) { //ctrl+i
+			self._inspectIt();
+			anEvent.preventDefault();
+			return false;
+		}
+	}>
+!
+
+inspectIt
+	self doIt inspect
+!
+
+print: aString
+	| start stop currentLine |
+	currentLine := (editor getCursor: false) line.
+	start := HashedCollection new.
+	start at: 'line' put: currentLine.
+	start at: 'ch' put: (editor getCursor: false) ch.
+	(editor getSelection) ifEmpty: [
+		"select current line if selection is empty"
+		start at: 'ch' put: (editor getLine: currentLine) size.
+		editor setSelection: #{'line' -> currentLine. 'ch' -> 0} end: start.
+	].
+	stop := HashedCollection new.
+	stop at: 'line' put: currentLine.
+	stop at: 'ch' put: ((start at: 'ch') + aString size + 2).
+
+	editor replaceSelection: (editor getSelection, ' ', aString, ' ').
+	editor setCursor: (editor getCursor: true).
+	editor setSelection: stop end: start
+!
+
+printIt
+	self print: self doIt printString.
+	self focus.
+! !
+
+!SourceArea methodsFor: 'events'!
+
+onKeyDown: aBlock
+	div onKeyDown: aBlock
+!
+
+onKeyUp: aBlock
+	div onKeyUp: aBlock
+! !
+
+!SourceArea methodsFor: 'rendering'!
+
+renderOn: html
+	| textarea |
+	div := html div class: 'source'.
+	div with: [ textarea := html textarea ].
+	self setEditorOn: textarea element.
+	div onKeyDown: [ :e | self handleKeyDown: e ]
+! !
+
+!SourceArea class methodsFor: 'accessing'!
+
+codeMirror
+	^ require value: 'codemirror/lib/codemirror'
+! !
+
+!SourceArea class methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+	self setupCodeMirror
+!
+
+setupCodeMirror
+	< self._codeMirror().keyMap["default"].fallthrough = ["basic"] >
+! !
+
+Widget subclass: #TabManager
+	instanceVariableNames: 'selectedTab tabs opened ul input'
+	package: 'IDE'!
+
+!TabManager methodsFor: 'accessing'!
+
+labelFor: aWidget
+	| label maxSize |
+	maxSize := 15.
+	label := aWidget label copyFrom: 0 to: (aWidget label size min: maxSize).
+	aWidget label size > maxSize ifTrue: [
+		label := label, '...' ].
+	^ label
+!
+
+tabs
+	^ tabs ifNil: [ tabs := Array new ]
+! !
+
+!TabManager methodsFor: 'actions'!
+
+close
+	opened ifTrue: [
+	'#amber' asJQuery hide.
+	ul asJQuery hide.
+	selectedTab hide.
+	self removeBodyMargin.
+	'body' asJQuery removeClass: 'amberBody'.
+	opened := false ]
+!
+
+closeTab: aWidget
+	self removeTab: aWidget.
+	self selectTab: self tabs last.
+	aWidget remove.
+	self update
+!
+
+newBrowserTab
+	Browser open
+!
+
+onResize: aBlock
+	'#amber' asJQuery resizable: #{
+		'handles' -> 'n'.
+		'resize' -> aBlock.
+		'minHeight' -> 230
+	}
+!
+
+onWindowResize: aBlock
+	window asJQuery resize: aBlock
+!
+
+open
+	opened ifFalse: [
+	'body' asJQuery addClass: 'amberBody'.
+	'#amber' asJQuery show.
+	ul asJQuery show.
+	self updateBodyMargin.
+	selectedTab show.
+	opened := true ]
+!
+
+removeBodyMargin
+	self setBodyMargin: 0
+!
+
+search: aString
+	| searchedClass |
+	searchedClass := Smalltalk globals at: aString.
+		searchedClass isClass
+			ifTrue: [ Browser openOn: searchedClass ]
+			ifFalse: [ ReferencesBrowser search: aString ]
+!
+
+selectTab: aWidget
+	self open.
+	selectedTab := aWidget.
+	self tabs do: [ :each |
+	each hide ].
+	aWidget show.
+	
+	self update
+!
+
+setBodyMargin: anInteger
+	'.amberBody' asJQuery css: 'margin-bottom' put: anInteger asString, 'px'
+!
+
+updateBodyMargin
+	self setBodyMargin: '#amber' asJQuery height
+!
+
+updatePosition
+	'#amber' asJQuery
+		css: 'top' put: '';
+		css: 'bottom' put: '0px'
+! !
+
+!TabManager methodsFor: 'adding/Removing'!
+
+addTab: aWidget
+	self tabs add: aWidget.
+	aWidget appendToJQuery: '#amber' asJQuery.
+	aWidget hide
+!
+
+removeTab: aWidget
+	self tabs remove: aWidget.
+	self update
+! !
+
+!TabManager methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+	Inspector register: IDEInspector.
+	opened := true.
+	[ :html | html div id: 'amber' ] appendToJQuery: 'body' asJQuery.
+	'body' asJQuery
+	addClass: 'amberBody'.
+	self appendToJQuery: '#amber' asJQuery.
+	self
+	addTab: IDETranscript current;
+	addTab: Workspace new;
+	addTab: TestRunner new.
+	self selectTab: self tabs last.
+	self
+	onResize: [ self updateBodyMargin; updatePosition ];
+	onWindowResize: [ self updatePosition ]
+! !
+
+!TabManager methodsFor: 'rendering'!
+
+renderOn: html
+	html div id: 'logo'.
+	self renderToolbarOn: html.
+	ul := html ul
+		id: 'amberTabs';
+		yourself.
+	self renderTabs
+!
+
+renderTabFor: aWidget on: html
+	| li |
+	li := html li.
+	selectedTab = aWidget ifTrue: [
+	li class: 'selected' ].
+	li with: [
+		html span class: 'ltab'.
+		html span
+			class: 'mtab';
+			with: [
+				aWidget canBeClosed ifTrue: [
+					html span
+						class: 'close';
+						with: 'x';
+					onClick: [ self closeTab: aWidget ]].
+			html span with: (self labelFor: aWidget) ].
+		html span class: 'rtab' ];
+	onClick: [ self selectTab: aWidget ]
+!
+
+renderTabs
+	ul contents: [ :html |
+		self tabs do: [ :each |
+		self renderTabFor: each on: html ].
+		html li
+		class: 'newtab';
+		with: [
+			html span class: 'ltab'.
+			html span class: 'mtab'; with: ' + '.
+			html span class: 'rtab' ];
+		onClick: [ self newBrowserTab ]]
+!
+
+renderToolbarOn: html
+	html div
+		id: 'amber_toolbar';
+		with: [
+			input := html input
+				class: 'implementors';
+				yourself.
+			input onKeyPress: [ :event |
+				event keyCode = 13 ifTrue: [
+				self search: input asJQuery val ]].
+			html div id: 'amber_close'; onClick: [ self close ]]
+! !
+
+!TabManager methodsFor: 'updating'!
+
+update
+	self renderTabs
+! !
+
+TabManager class instanceVariableNames: 'current'!
+
+!TabManager class methodsFor: 'actions'!
+
+toggleAmberIDE
+	'#amber' asJQuery length = 0
+		ifTrue: [ Browser open ]
+		ifFalse: [
+			('#amber' asJQuery is: ':visible')
+				ifTrue: [ TabManager current close ]
+				ifFalse: [ TabManager current open ] ]
+! !
+
+!TabManager class methodsFor: 'instance creation'!
+
+current
+	^ current ifNil: [ current := super new ]
+!
+
+new
+	self shouldNotImplement
+! !
+
+Widget subclass: #TabWidget
+	instanceVariableNames: 'div'
+	package: 'IDE'!
+
+!TabWidget methodsFor: 'accessing'!
+
+label
+	self subclassResponsibility
+! !
+
+!TabWidget methodsFor: 'actions'!
+
+close
+	TabManager current closeTab: self
+!
+
+hide
+	div asJQuery hide
+!
+
+open
+	TabManager current addTab: self.
+	TabManager current selectTab: self
+!
+
+remove
+	div asJQuery remove
+!
+
+show
+	div asJQuery show
+! !
+
+!TabWidget methodsFor: 'rendering'!
+
+renderBoxOn: html
+!
+
+renderButtonsOn: html
+!
+
+renderOn: html
+	div := html div
+		class: 'amberTool';
+		yourself.
+	self renderTab
+!
+
+renderTab
+	div contents: [ :html |
+		html div
+		class: 'amber_box';
+		with: [ self renderBoxOn: html ].
+		html div
+		class: 'amber_buttons';
+		with: [ self renderButtonsOn: html ]]
+!
+
+update
+	self renderTab
+! !
+
+!TabWidget methodsFor: 'testing'!
+
+canBeClosed
+	^ false
+! !
+
+!TabWidget class methodsFor: 'instance creation'!
+
+open
+	^ self new open
+! !
+
+TabWidget subclass: #Browser
+	instanceVariableNames: 'selectedPackage selectedClass selectedProtocol selectedMethod packagesList classesList protocolsList methodsList sourceArea tabsList selectedTab saveButton classButtons methodButtons unsavedChanges'
+	package: 'IDE'!
+
+!Browser methodsFor: 'accessing'!
+
+classCommentSource
+	^ selectedClass comment
+!
+
+classDeclarationSource
+	| stream |
+	stream := '' writeStream.
+	selectedClass ifNil: [ ^ self classDeclarationTemplate ].
+	stream
+		nextPutAll: selectedClass superclass asString;
+		nextPutAll: ' subclass: #';
+		nextPutAll: selectedClass name;
+		nextPutAll: String lf, String tab;
+		nextPutAll: 'instanceVariableNames: '''.
+	selectedClass instanceVariableNames
+		do: [ :each | stream nextPutAll: each ]
+		separatedBy: [ stream nextPutAll: ' ' ].
+	stream
+		nextPutAll: '''', String lf, String tab;
+		nextPutAll: 'package: ''';
+		nextPutAll: selectedClass category;
+		nextPutAll: ''''.
+	^ stream contents
+!
+
+classDeclarationTemplate
+	^ 'Object subclass: #NameOfSubclass
+	instanceVariableNames: ''''
+	package: ''', self selectedPackage, ''''
+!
+
+classes
+	^ ((Smalltalk classes
+	select: [ :each | each category = selectedPackage ])
+	sort: [ :a :b | a name < b name ]) asSet
+!
+
+declarationSource
+	^ selectedTab = #instance
+	ifTrue: [ self classDeclarationSource ]
+	ifFalse: [ self metaclassDeclarationSource ]
+!
+
+dummyMethodSource
+	^ 'messageSelectorAndArgumentNames
+	"comment stating purpose of message"
+
+	| temporary variable names |
+	statements'
+!
+
+label
+	^ selectedClass
+	ifNil: [ 'Browser (nil)' ]
+	ifNotNil: [ 'Browser: ', selectedClass name ]
+!
+
+metaclassDeclarationSource
+	| stream |
+	stream := '' writeStream.
+	selectedClass ifNotNil: [
+	stream
+		nextPutAll: selectedClass asString;
+		nextPutAll: ' class ';
+		nextPutAll: 'instanceVariableNames: '''.
+	selectedClass class instanceVariableNames
+		do: [ :each | stream nextPutAll: each ]
+		separatedBy: [ stream nextPutAll: ' ' ].
+	stream nextPutAll: '''' ].
+	^ stream contents
+!
+
+methodSource
+	^ selectedMethod
+	ifNil: [ self dummyMethodSource ]
+	ifNotNil: [ selectedMethod source ]
+!
+
+methods
+	| klass |
+	selectedTab = #comment ifTrue: [ ^ #() ].
+	selectedClass ifNotNil: [
+	klass := selectedTab = #instance
+		ifTrue: [ selectedClass ]
+		ifFalse: [ selectedClass class ]].
+	^ (selectedProtocol
+	ifNil: [
+		klass
+		ifNil: [ #() ]
+		ifNotNil: [ klass methodDictionary values ]]
+	ifNotNil: [
+		klass methodsInProtocol: selectedProtocol ]) 
+				sort: [ :a :b | a selector < b selector ]
+!
+
+packages
+	| packages |
+	packages := Array new.
+	Smalltalk classes do: [ :each |
+	(packages includes: each category) ifFalse: [
+		packages add: each category ]].
+	^ packages sort
+!
+
+protocols
+	| klass |
+	selectedClass ifNotNil: [
+	selectedTab = #comment ifTrue: [ ^ #() ].
+	klass := selectedTab = #instance
+		ifTrue: [ selectedClass ]
+		ifFalse: [ selectedClass class ].
+	klass methodDictionary isEmpty ifTrue: [
+		^ Array with: 'not yet classified' ].
+	^ klass protocols ].
+	^ Array new
+!
+
+selectedClass
+	^ selectedClass
+!
+
+selectedPackage
+	^ selectedPackage
+!
+
+source
+	selectedTab = #comment ifFalse: [
+	^ (selectedProtocol notNil or: [ selectedMethod notNil ])
+		ifFalse: [ self declarationSource ]
+		ifTrue: [ self methodSource ]].
+	^ selectedClass
+	ifNil: [ '' ]
+	ifNotNil: [ self classCommentSource ]
+! !
+
+!Browser methodsFor: 'actions'!
+
+addInstanceVariableNamed: aString toClass: aClass
+	ClassBuilder new
+		addSubclassOf: aClass superclass
+		named: aClass name
+		instanceVariableNames: (aClass instanceVariableNames copy add: aString; yourself)
+		package: aClass package name
+!
+
+addNewClass
+	| className |
+	className := self prompt: 'New class'.
+	(className notNil and: [ className notEmpty ]) ifTrue: [
+		Object subclass: className instanceVariableNames: '' package: self selectedPackage.
+			self
+			resetClassesList;
+			updateClassesList.
+		self selectClass: (Smalltalk globals at: className) ]
+!
+
+addNewProtocol
+	| newProtocol |
+	
+	newProtocol := self prompt: 'New method protocol'.
+	
+	(newProtocol notNil and: [ newProtocol notEmpty ]) ifTrue: [
+		selectedMethod protocol: newProtocol.
+		self setMethodProtocol: newProtocol ]
+!
+
+cancelChanges
+	^ unsavedChanges
+	ifTrue: [ self confirm: 'Cancel changes?' ]
+	ifFalse: [ true ]
+!
+
+commitPackage
+	selectedPackage ifNotNil: [
+		(Package named: selectedPackage) commit ]
+!
+
+compile
+	| currentEditLine |
+	self disableSaveButton.
+	currentEditLine := sourceArea editor getCursor.
+	selectedTab = #comment
+	ifTrue: [
+			selectedClass ifNotNil: [
+				self compileClassComment ]]
+	ifFalse: [
+			(selectedProtocol notNil or: [ selectedMethod notNil ])
+				ifFalse: [ self compileDefinition ]
+				ifTrue: [ self compileMethodDefinition ]].
+	sourceArea editor setCursor: currentEditLine.
+!
+
+compileClassComment
+	selectedClass comment: sourceArea val
+!
+
+compileDefinition
+	| newClass |
+	newClass := Compiler new evaluateExpression: sourceArea val.
+	self
+	resetClassesList;
+	updateCategoriesList;
+	updateClassesList.
+	self selectClass: newClass
+!
+
+compileMethodDefinition
+	selectedTab = #instance
+	ifTrue: [ self compileMethodDefinitionFor: selectedClass ]
+	ifFalse: [ self compileMethodDefinitionFor: selectedClass class ]
+!
+
+compileMethodDefinitionFor: aClass
+	| compiler method source node |
+	source := sourceArea val.
+	selectedProtocol ifNil: [ selectedProtocol := selectedMethod protocol ].
+	compiler := Compiler new.
+	compiler source: source.
+	node := compiler parse: source.
+	node isParseFailure ifTrue: [
+	^ self alert: 'PARSE ERROR: ', node reason, ', position: ', node position asString ].
+	compiler currentClass: aClass.
+	method := compiler eval: (compiler compileNode: node).
+	compiler unknownVariables do: [ :each |
+		"Do not try to redeclare javascript's objects"
+		(PlatformInterface existsGlobal: each) ifFalse: [
+		(self confirm: 'Declare ''', each, ''' as instance variable?') ifTrue: [
+			self addInstanceVariableNamed: each toClass: aClass.
+			^ self compileMethodDefinitionFor: aClass ]] ].
+	ClassBuilder new installMethod: method forClass: aClass protocol: selectedProtocol.
+	self updateMethodsList.
+	self selectMethod: method
+!
+
+copyClass
+	| className |
+	className := self prompt: 'Copy class'.
+	(className notNil and: [ className notEmpty ]) ifTrue: [
+		ClassBuilder new copyClass: self selectedClass named: className.
+			self
+			resetClassesList;
+			updateClassesList.
+		self selectClass: (Smalltalk globals at: className) ]
+!
+
+disableSaveButton
+	saveButton ifNotNil: [
+	saveButton at: 'disabled' put: true ].
+	unsavedChanges := false
+!
+
+handleSourceAreaKeyDown: anEvent
+	<if(anEvent.ctrlKey) {
+		if(anEvent.keyCode === 83) { //ctrl+s
+			self._compile();
+			anEvent.preventDefault();
+			return false;
+		}
+	}
+	>
+!
+
+hideClassButtons
+	classButtons asJQuery hide
+!
+
+hideMethodButtons
+	methodButtons asJQuery hide
+!
+
+removeClass
+	(self confirm: 'Do you really want to remove ', selectedClass name, '?')
+	ifTrue: [
+		Smalltalk removeClass: selectedClass.
+		self resetClassesList.
+		self selectClass: nil ]
+!
+
+removeMethod
+	self cancelChanges ifTrue: [
+	(self confirm: 'Do you really want to remove #', selectedMethod selector, '?')
+		ifTrue: [
+		selectedTab = #instance
+			ifTrue: [ selectedClass removeCompiledMethod: selectedMethod ]
+			ifFalse: [ selectedClass class removeCompiledMethod: selectedMethod ].
+		self selectMethod: nil ]]
+!
+
+removePackage
+
+	(self confirm: 'Do you really want to remove the whole package ', selectedPackage, ' with all its classes?')
+	ifTrue: [
+		Smalltalk removePackage: selectedPackage.
+		self updateCategoriesList ]
+!
+
+renameClass
+	| newName |
+	newName := self prompt: 'Rename class ', selectedClass name.
+	(newName notNil and: [ newName notEmpty ]) ifTrue: [
+	selectedClass rename: newName.
+	self
+		updateClassesList;
+		updateSourceAndButtons ]
+!
+
+renamePackage
+
+	| newName |
+	newName := self prompt: 'Rename package ', selectedPackage.
+	newName ifNotNil: [
+	newName notEmpty ifTrue: [
+	Smalltalk renamePackage: selectedPackage to: newName.
+	self updateCategoriesList ]]
+!
+
+search: aString
+	self cancelChanges ifTrue: [ | searchedClass |
+		searchedClass := Smalltalk globals at: aString.
+		searchedClass isClass
+			ifTrue: [ self class openOn: searchedClass ]
+			ifFalse: [ self searchReferencesOf: aString ]]
+!
+
+searchClassReferences
+	ReferencesBrowser search: selectedClass name
+!
+
+searchReferencesOf: aString
+	ReferencesBrowser search: aString
+!
+
+selectCategory: aCategory
+	self cancelChanges ifTrue: [
+	selectedPackage := aCategory.
+	selectedClass := selectedProtocol := selectedMethod := nil.
+	self resetClassesList.
+	self
+		updateCategoriesList;
+		updateClassesList;
+		updateProtocolsList;
+		updateMethodsList;
+		updateSourceAndButtons ]
+!
+
+selectClass: aClass
+	self cancelChanges ifTrue: [
+	selectedClass := aClass.
+	selectedProtocol := selectedMethod := nil.
+	self
+		updateClassesList;
+		updateProtocolsList;
+		updateMethodsList;
+		updateSourceAndButtons ]
+!
+
+selectMethod: aMethod
+	self cancelChanges ifTrue: [
+	selectedMethod := aMethod.
+	self
+		updateProtocolsList;
+		updateMethodsList;
+		updateSourceAndButtons ]
+!
+
+selectProtocol: aString
+	self cancelChanges ifTrue: [
+	selectedProtocol := aString.
+	selectedMethod := nil.
+	self
+		updateProtocolsList;
+		updateMethodsList;
+		updateSourceAndButtons ]
+!
+
+selectTab: aString
+	self cancelChanges ifTrue: [
+	selectedTab := aString.
+	self selectProtocol: nil.
+	self updateTabsList ]
+!
+
+setMethodProtocol: aString
+	self cancelChanges ifTrue: [
+	(self protocols includes: aString)
+		ifFalse: [ self addNewProtocol ]
+		ifTrue: [
+		selectedMethod protocol: aString.
+		selectedProtocol := aString.
+		selectedMethod := selectedMethod.
+		self
+			updateProtocolsList;
+			updateMethodsList;
+			updateSourceAndButtons ]]
+!
+
+showClassButtons
+	classButtons asJQuery show
+!
+
+showMethodButtons
+	methodButtons asJQuery show
+! !
+
+!Browser methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+	selectedTab := #instance.
+	selectedPackage := self packages first.
+	unsavedChanges := false
+! !
+
+!Browser methodsFor: 'rendering'!
+
+renderBottomPanelOn: html
+	html div
+	class: 'amber_sourceCode';
+	with: [
+		sourceArea := SourceArea new.
+		sourceArea renderOn: html.
+			sourceArea onKeyDown: [ :e |
+				self handleSourceAreaKeyDown: e ].
+		sourceArea onKeyUp: [ self updateStatus ]]
+!
+
+renderBoxOn: html
+	self
+	renderTopPanelOn: html;
+	renderTabsOn: html;
+	renderBottomPanelOn: html
+!
+
+renderButtonsOn: html
+	saveButton := html button.
+	saveButton
+	with: 'Save';
+	onClick: [ self compile ].
+	methodButtons := html span.
+	classButtons := html span.
+	html div
+	class: 'right';
+	with: [
+		html button
+			with: 'DoIt';
+			onClick: [ sourceArea doIt ].
+		html button
+			with: 'PrintIt';
+			onClick: [ sourceArea printIt ].
+		html button with: 'InspectIt';
+			onClick: [ sourceArea inspectIt ]].
+	self updateSourceAndButtons
+!
+
+renderTabsOn: html
+	tabsList := html ul class: 'amber_tabs amber_browser'.
+	self updateTabsList.
+!
+
+renderTopPanelOn: html
+	html div
+		class: 'top';
+		with: [
+			packagesList := html ul class: 'amber_column browser packages'.
+				html div class: 'amber_packagesButtons'; with: [
+				html button
+					title: 'Commit classes in this package to disk';
+					onClick: [ self commitPackage ];
+					with: 'Commit'.
+					html button
+					title: 'Rename package';
+					onClick: [ self renamePackage ];
+					with: 'Rename'.
+					html button
+					title: 'Remove this package from the system';
+					onClick: [ self removePackage ];
+					with: 'Remove' ].
+			classesList := ClassesList on: self.
+			classesList renderOn: html.
+			protocolsList := html ul class: 'amber_column browser protocols'.
+			methodsList := html ul class: 'amber_column browser methods'.
+			self
+				updateCategoriesList;
+				updateClassesList;
+				updateProtocolsList;
+				updateMethodsList.
+			html div class: 'amber_clear' ]
+! !
+
+!Browser methodsFor: 'testing'!
+
+canBeClosed
+	^ true
+! !
+
+!Browser methodsFor: 'updating'!
+
+resetClassesList
+	classesList resetNodes
+!
+
+updateCategoriesList
+	packagesList contents: [ :html |
+	self packages do: [ :each || li label |
+		each isEmpty
+		ifTrue: [ label := 'Unclassified' ]
+		ifFalse: [ label := each ].
+		li := html li.
+		selectedPackage = each ifTrue: [
+		li class: 'selected' ].
+		li
+		with: label;
+		onClick: [ self selectCategory: each ]] ]
+!
+
+updateClassesList
+	TabManager current update.
+	classesList updateNodes
+!
+
+updateMethodsList
+	methodsList contents: [ :html |
+	self methods do: [ :each || li |
+		li := html li.
+		selectedMethod = each ifTrue: [
+		li class: 'selected' ].
+		li
+		with: each selector;
+		onClick: [ self selectMethod: each ]] ]
+!
+
+updateProtocolsList
+	protocolsList contents: [ :html |
+	self protocols do: [ :each || li |
+		li := html li.
+		selectedProtocol = each ifTrue: [
+		li class: 'selected' ].
+		li
+		with: each;
+		onClick: [ self selectProtocol: each ]] ]
+!
+
+updateSourceAndButtons
+	| currentProtocol |
+
+	self disableSaveButton.
+	classButtons contents: [ :html |
+		html button
+			title: 'Create a new class';
+			onClick: [ self addNewClass ];
+			with: 'New class'.
+		html button
+			with: 'Rename class';
+			onClick: [ self renameClass ].
+		html button
+			with: 'Copy class';
+			onClick: [ self copyClass ].
+		html button
+			with: 'Remove class';
+			onClick: [ self removeClass ].
+		html button
+			with: 'References';
+			onClick: [ self searchClassReferences ]].
+	methodButtons contents: [ :html | | protocolSelect referencesSelect |
+		html button
+			with: 'Remove method';
+			onClick: [ self removeMethod ].
+		protocolSelect := html select.
+				protocolSelect
+			onChange: [ self setMethodProtocol: protocolSelect asJQuery val ];
+			with: [
+				html option
+					with: 'Method protocol';
+					at: 'disabled' put: 'disabled'.
+				html option
+					class: 'important';
+					with: 'New...'.
+				currentProtocol := selectedProtocol.
+				(currentProtocol isNil and: [ selectedMethod notNil ])
+					ifTrue: [ currentProtocol := selectedMethod category ].
+				self protocols do: [ :each | | option |
+					option := html option with: each.
+					currentProtocol = each ifTrue: [ option at: 'selected' put: 'selected' ] ] ].
+		selectedMethod isNil ifFalse: [
+			referencesSelect := html select.
+						referencesSelect
+				onChange: [ self searchReferencesOf: referencesSelect asJQuery val ];
+				with: [ |option|
+					html option
+						with: 'References';
+						at: 'disabled' put: 'disabled';
+						at: 'selected' put: 'selected'.
+					html option
+						class: 'important';
+						with: selectedMethod selector.
+					selectedMethod messageSends sorted do: [ :each |
+						html option with: each ]] ]].
+	selectedMethod isNil
+		ifTrue: [
+			self hideMethodButtons.
+				(selectedClass isNil or: [ selectedProtocol notNil ])
+					ifTrue: [ self hideClassButtons ]
+					ifFalse: [ self showClassButtons ]]
+		ifFalse: [
+			self hideClassButtons.
+			self showMethodButtons ].
+	sourceArea val: self source
+!
+
+updateStatus
+	sourceArea val = self source
+		ifTrue: [
+			saveButton ifNotNil: [
+				saveButton at: 'disabled' put: true ].
+				unsavedChanges := false ]
+		ifFalse: [
+			saveButton ifNotNil: [
+				saveButton removeAt: 'disabled' ].
+			unsavedChanges := true ]
+!
+
+updateTabsList
+	tabsList contents: [ :html || li |
+	li := html li.
+	selectedTab = #instance ifTrue: [ li class: 'selected' ].
+	li
+		with: [
+		html span class: 'ltab'.
+		html span class: 'mtab'; with: 'Instance'.
+		html span class: 'rtab' ];
+		onClick: [ self selectTab: #instance ].
+	li := html li.
+	selectedTab = #class ifTrue: [ li class: 'selected' ].
+	li
+		with: [
+		html span class: 'ltab'.
+		html span class: 'mtab'; with: 'Class'.
+		html span class: 'rtab' ];
+		onClick: [ self selectTab: #class ].
+	li := html li.
+	selectedTab = #comment ifTrue: [ li class: 'selected' ].
+	li
+		with: [
+		html span class: 'ltab'.
+		html span class: 'mtab'; with: 'Comment'.
+		html span class: 'rtab' ];
+		onClick: [ self selectTab: #comment ]]
+! !
+
+!Browser class methodsFor: 'convenience'!
+
+open
+	self new open
+!
+
+openOn: aClass
+	^ self new
+	open;
+	selectCategory: aClass category;
+	selectClass: aClass
+! !
+
+TabWidget subclass: #Debugger
+	instanceVariableNames: 'error selectedContext sourceArea ul ul2 inspector saveButton unsavedChanges selectedVariable selectedVariableName inspectButton'
+	package: 'IDE'!
+
+!Debugger methodsFor: 'accessing'!
+
+allVariables
+	| all |
+	all := Dictionary new.
+
+	self receiver class allInstanceVariableNames do: [ :each |
+		all at: each put: (self receiver instVarAt: each) ].
+	
+	selectedContext locals keysAndValuesDo: [ :key :value |
+		all at: key put: value ].
+	
+	^ all
+!
+
+error
+	^ error
+!
+
+error: anError
+	error := anError
+!
+
+label
+	^ '[ Debugger ]'
+!
+
+method
+	^ selectedContext method
+!
+
+receiver
+	^ selectedContext receiver
+!
+
+source
+	^ self method
+		ifNil: [ 'Method doesn''t exist!!' ]
+		ifNotNil: [ self method source ]
+! !
+
+!Debugger methodsFor: 'actions'!
+
+inspectSelectedVariable
+	selectedVariable inspect
+!
+
+proceed
+	self close.
+	selectedContext receiver perform: selectedContext selector withArguments: selectedContext locals
+!
+
+save
+	| protocol |
+	protocol := (selectedContext receiver class methodDictionary at: selectedContext selector) category.
+	selectedContext receiver class compile: sourceArea val protocol: protocol.
+	self updateStatus
+!
+
+selectContext: aContext
+	selectedContext := aContext.
+	selectedVariable := nil.
+	selectedVariableName := nil.
+	self
+		updateContextsList;
+		updateSourceArea;
+		updateInspector;
+		updateVariablesList;
+		updateStatus
+!
+
+selectVariable: anObject named: aString
+	
+	selectedVariable := anObject.
+	selectedVariableName := aString.
+	inspector contents: [ :html | html with: anObject printString ].
+	self updateVariablesList
+! !
+
+!Debugger methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+	unsavedChanges = false
+! !
+
+!Debugger methodsFor: 'rendering'!
+
+renderBottomPanelOn: html
+	html div
+		class: 'amber_sourceCode debugger';
+		with: [
+			sourceArea := SourceArea new.
+			sourceArea renderOn: html ].
+	ul2 := html ul class: 'amber_column debugger variables'.
+	inspector := html div class: 'amber_column debugger inspector'.
+	sourceArea
+		onKeyUp: [ self updateStatus ]
+!
+
+renderBoxOn: html
+	self
+		renderTopPanelOn: html;
+		renderBottomPanelOn: html
+!
+
+renderButtonsOn: html
+	saveButton := html button
+		with: 'Save';
+		onClick: [ self save ].
+	html button
+		with: 'DoIt';
+		onClick: [ sourceArea doIt ].
+	html button
+		with: 'PrintIt';
+		onClick: [ sourceArea printIt ].
+	html button
+		with: 'InspectIt';
+		onClick: [ sourceArea inspectIt ].
+	html button
+		with: 'Proceed';
+		onClick: [ self proceed ].
+	html button
+		with: 'Abandon';
+		onClick: [ self close ].
+	inspectButton := html button
+		class: 'amber_button debugger inspect';
+		with: 'Inspect';
+		onClick: [ self inspectSelectedVariable ].
+	self
+		updateSourceArea;
+		updateStatus;
+		updateVariablesList;
+		updateInspector
+!
+
+renderContext: aContext on: html
+	| li |
+	li := html li.
+	selectedContext = aContext ifTrue: [
+		li class: 'selected' ].
+	li
+		with: aContext asString;
+		onClick: [ self selectContext: aContext ].
+	aContext outerContext ifNotNil: [ self renderContext: aContext outerContext on: html ]
+!
+
+renderTopPanelOn: html
+	selectedContext := self error context.
+	html div
+		class: 'top';
+		with: [
+			html div
+				class: 'label';
+				with: self error messageText.
+			ul := html ul
+				class: 'amber_column debugger contexts';
+				with: [ self renderContext: self error context on: html ]]
+! !
+
+!Debugger methodsFor: 'testing'!
+
+canBeClosed
+	^ true
+! !
+
+!Debugger methodsFor: 'updating'!
+
+updateContextsList
+	ul contents: [ :html |
+		self renderContext: self error context on: html ]
+!
+
+updateInspector
+	inspector contents: [ :html | ]
+!
+
+updateSourceArea
+	sourceArea val: self source
+!
+
+updateStatus
+	sourceArea val = self source
+		ifTrue: [
+			saveButton ifNotNil: [
+				saveButton at: 'disabled' put: true ].
+			unsavedChanges := false ]
+		ifFalse: [
+			saveButton ifNotNil: [
+				saveButton removeAt: 'disabled' ].
+			unsavedChanges := true ]
+!
+
+updateVariablesList
+	ul2 contents: [ :html | | li |
+		li := html li
+			with: 'self';
+			onClick: [ self selectVariable: self receiver named: 'self' ].
+				selectedVariableName = 'self' ifTrue: [ li class: 'selected' ].
+		
+		self allVariables keysAndValuesDo: [ :key :value |
+						li := html li
+							with: key;
+							onClick: [ self selectVariable: value named: key ].
+						selectedVariableName = key ifTrue: [
+							li class: 'selected' ] ] ].
+							
+	selectedVariable
+		ifNil: [ inspectButton at: 'disabled' put: true ]
+		ifNotNil: [ inspectButton removeAt: 'disabled' ]
+! !
+
+TabWidget subclass: #IDEInspector
+	instanceVariableNames: 'label variables object selectedVariable variablesList valueTextarea diveButton sourceArea'
+	package: 'IDE'!
+
+!IDEInspector methodsFor: 'accessing'!
+
+label
+	^ label ifNil: [ 'Inspector (nil)' ]
+!
+
+selectedVariable
+	^ selectedVariable
+!
+
+selectedVariable: aString
+	selectedVariable := aString
+!
+
+setLabel: aString
+	label := aString
+!
+
+setVariables: aCollection
+	variables := aCollection
+!
+
+sourceArea
+	^ sourceArea
+!
+
+variables
+	^ variables
+! !
+
+!IDEInspector methodsFor: 'actions'!
+
+dive
+	(self variables at: self selectedVariable) inspect
+!
+
+inspect: anObject
+	object := anObject.
+	variables := #().
+	object inspectOn: self
+!
+
+refresh
+	self
+		inspect: object;
+		updateVariablesList;
+		updateValueTextarea
+! !
+
+!IDEInspector methodsFor: 'rendering'!
+
+renderBottomPanelOn: html
+	html div
+	class: 'amber_sourceCode';
+	with: [
+		sourceArea := SourceArea new
+		receiver: object;
+		onDoIt: [ self refresh ];
+		yourself.
+			sourceArea renderOn: html ]
+!
+
+renderBoxOn: html
+	self
+		renderTopPanelOn: html;
+		renderBottomPanelOn: html
+!
+
+renderButtonsOn: html
+	html button
+		with: 'DoIt';
+		onClick: [ self sourceArea doIt ].
+	html button
+		with: 'PrintIt';
+		onClick: [ self sourceArea printIt ].
+	html button
+		with: 'InspectIt';
+		onClick: [ self sourceArea inspectIt ].
+	self updateButtons
+!
+
+renderTopPanelOn: html
+	html div
+		class: 'top';
+		with: [
+			variablesList := html ul class: 'amber_column variables'.
+			valueTextarea := html textarea class: 'amber_column value'; at: 'readonly' put: 'readonly'; yourself.
+			html div class: 'amber_tabs inspector'; with: [
+				html button
+					class: 'amber_button inspector refresh';
+					with: 'Refresh';
+					onClick: [ self refresh ].
+				diveButton := html button
+					class: 'amber_button inspector dive';
+					with: 'Dive';
+					onClick: [ self dive ]].
+			html div class: 'amber_clear' ].
+	self
+		updateVariablesList;
+		updateValueTextarea.
+! !
+
+!IDEInspector methodsFor: 'testing'!
+
+canBeClosed
+	^ true
+! !
+
+!IDEInspector methodsFor: 'updating'!
+
+selectVariable: aString
+	self selectedVariable: aString.
+	self
+		updateVariablesList;
+		updateValueTextarea;
+		updateButtons
+!
+
+updateButtons
+	(self selectedVariable notNil and: [ (self variables at: self selectedVariable) notNil ])
+		ifFalse: [ diveButton at: 'disabled' put: true ]
+		ifTrue: [ diveButton removeAt: 'disabled' ]
+!
+
+updateValueTextarea
+	valueTextarea asJQuery val: (self selectedVariable isNil
+		ifTrue: [ '' ]
+		ifFalse: [ (self variables at: self selectedVariable) printString ])
+!
+
+updateVariablesList
+	variablesList contents: [ :html |
+		self variables keysDo: [ :each || li |
+			li := html li.
+			li
+				with: each;
+				onClick: [ self selectVariable: each ].
+			self selectedVariable = each ifTrue: [
+				li class: 'selected' ]] ]
+! !
+
+!IDEInspector class methodsFor: 'instance creation'!
+
+inspect: anObject
+	^ self new
+		inspect: anObject;
+		open;
+		yourself
+!
+
+on: anObject
+	^ self new
+		inspect: anObject;
+		yourself
+! !
+
+TabWidget subclass: #IDETranscript
+	instanceVariableNames: 'textarea'
+	package: 'IDE'!
+
+!IDETranscript methodsFor: 'accessing'!
+
+label
+	^ 'Transcript'
+! !
+
+!IDETranscript methodsFor: 'actions'!
+
+clear
+	textarea asJQuery val: ''
+!
+
+cr
+	textarea asJQuery val: textarea asJQuery val, String cr.
+!
+
+open
+	TabManager current
+	open;
+	selectTab: self
+!
+
+show: anObject
+	textarea ifNil: [ self open ].
+	textarea asJQuery val: textarea asJQuery val, anObject asString.
+! !
+
+!IDETranscript methodsFor: 'rendering'!
+
+renderBoxOn: html
+	textarea := html textarea.
+	textarea
+	class: 'amber_transcript';
+	at: 'spellcheck' put: 'false'
+!
+
+renderButtonsOn: html
+	html button
+	with: 'Clear transcript';
+	onClick: [ self clear ]
+! !
+
+IDETranscript class instanceVariableNames: 'current'!
+
+!IDETranscript class methodsFor: 'initialization'!
+
+initialize
+	Transcript register: self current
+! !
+
+!IDETranscript class methodsFor: 'instance creation'!
+
+current
+	^ current ifNil: [ current := super new ]
+!
+
+new
+	self shouldNotImplement
+!
+
+open
+	TabManager current
+		open;
+		selectTab: self current
+! !
+
+TabWidget subclass: #ProgressBar
+	instanceVariableNames: 'percent progressDiv div'
+	package: 'IDE'!
+
+!ProgressBar methodsFor: 'accessing'!
+
+percent
+	^ percent ifNil: [ 0 ]
+!
+
+percent: aNumber
+	percent := aNumber
+! !
+
+!ProgressBar methodsFor: 'rendering'!
+
+renderOn: html
+	div := html div
+		class: 'progress_bar';
+		yourself.
+	self renderProgressBar
+!
+
+renderProgressBar
+	div contents: [ :html |
+		html div
+			class: 'progress';
+			style: 'width:', self percent asString, '%' ]
+! !
+
+!ProgressBar methodsFor: 'updating'!
+
+updatePercent: aNumber
+	self percent: aNumber.
+	self renderProgressBar
+! !
+
+TabWidget subclass: #ReferencesBrowser
+	instanceVariableNames: 'implementors senders implementorsList input timer selector sendersList referencedClasses referencedClassesList matches matchesList'
+	package: 'IDE'!
+
+!ReferencesBrowser methodsFor: 'accessing'!
+
+classesAndMetaclasses
+	^ Smalltalk classes, (Smalltalk classes collect: [ :each | each class ])
+!
+
+implementors
+	^ implementors ifNil: [ implementors := Array new ]
+!
+
+label
+	^ '[ References ]'
+!
+
+matches
+	^ matches ifNil: [ matches := Array new ]
+!
+
+referencedClasses
+	^ referencedClasses ifNil: [ referencedClasses := Array new ]
+!
+
+selector
+	^ selector
+!
+
+senders
+	^ senders ifNil: [ senders := Array new ]
+! !
+
+!ReferencesBrowser methodsFor: 'actions'!
+
+openBrowserOn: aMethod
+	| browser |
+	browser := Browser openOn: (aMethod methodClass isMetaclass
+		ifTrue: [ aMethod methodClass instanceClass ] ifFalse: [ aMethod methodClass ]).
+	aMethod methodClass isMetaclass ifTrue: [ browser selectTab: #class ].
+	browser
+		selectProtocol: aMethod category;
+		selectMethod: aMethod
+!
+
+search: aString
+	self
+		searchReferencesFor: aString;
+		updateImplementorsList;
+		updateSendersList;
+		updateReferencedClassesList;
+		updateMatchesList
+!
+
+searchMethodSource
+	| regex |
+	regex := selector allButFirst.
+	self classesAndMetaclasses do: [ :each |
+		each methodDictionary valuesDo: [ :value |
+			(value source match: regex) ifTrue: [
+				self matches add: value ]] ]
+!
+
+searchReferencedClasses
+	self classesAndMetaclasses do: [ :each |
+		each methodDictionary valuesDo: [ :value |
+			(value referencedClasses includes: selector) ifTrue: [
+				self referencedClasses add: value ]] ]
+!
+
+searchReferencesFor: aString
+	selector := aString.
+	implementors := Array new.
+	senders := Array new.
+	referencedClasses := Array new.
+	matches := Array new.
+	self searchMethodSource.
+	(selector match: '^[A-Z]')
+		ifFalse: [ self searchSelectorReferences ]
+		ifTrue: [ self searchReferencedClasses ]
+!
+
+searchSelectorReferences
+	self classesAndMetaclasses do: [ :each |
+		each methodDictionary keysAndValuesDo: [ :key :value |
+			key = selector ifTrue: [ self implementors add: value ].
+			(value messageSends includes: selector) ifTrue: [
+				self senders add: value ]] ]
+! !
+
+!ReferencesBrowser methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+	selector := ''
+! !
+
+!ReferencesBrowser methodsFor: 'private'!
+
+setInputEvents
+	input
+		onKeyUp: [ timer := [ self search: input asJQuery val ] valueWithTimeout: 100 ];
+		onKeyDown: [ timer ifNotNil: [ timer clearTimeout ]]
+! !
+
+!ReferencesBrowser methodsFor: 'rendering'!
+
+renderBoxOn: html
+	self
+		renderInputOn: html;
+		renderImplementorsOn: html;
+		renderSendersOn: html;
+		renderReferencedClassesOn: html;
+		renderMatchesOn: html
+!
+
+renderImplementorsOn: html
+	implementorsList := html ul class: 'amber_column implementors'.
+	self updateImplementorsList
+!
+
+renderInputOn: html
+	input := html input
+		class: 'implementors';
+		yourself.
+	input asJQuery val: selector.
+	self setInputEvents
+!
+
+renderMatchesOn: html
+	matchesList := html ul class: 'amber_column matches'.
+	self updateMatchesList
+!
+
+renderReferencedClassesOn: html
+	referencedClassesList := html ul class: 'amber_column referenced_classes'.
+	self updateReferencedClassesList
+!
+
+renderSendersOn: html
+	sendersList := html ul class: 'amber_column senders'.
+	self updateSendersList
+! !
+
+!ReferencesBrowser methodsFor: 'testing'!
+
+canBeClosed
+	^ true
+! !
+
+!ReferencesBrowser methodsFor: 'updating'!
+
+updateImplementorsList
+	implementorsList contents: [ :html |
+	html li
+		class: 'column_label';
+		with: 'Implementors (', self implementors size asString, ')';
+		style: 'font-weight: bold'.
+	self implementors do: [ :each || li |
+		li := html li.
+		li
+		with: (each methodClass asString, ' >> ', self selector);
+		onClick: [ self openBrowserOn: each ]] ]
+!
+
+updateMatchesList
+	matchesList contents: [ :html |
+	html li
+		class: 'column_label';
+		with: 'Regex matches (', self matches size asString, ')';
+		style: 'font-weight: bold'.
+	self matches do: [ :each || li |
+		li := html li.
+		li
+		with: (each methodClass asString, ' >> ', each selector);
+		onClick: [ self openBrowserOn: each ]] ]
+!
+
+updateReferencedClassesList
+	referencedClassesList contents: [ :html |
+	html li
+		class: 'column_label';
+		with: 'Class references (', self referencedClasses size asString, ')';
+		style: 'font-weight: bold'.
+	self referencedClasses do: [ :each |
+		html li
+			with: (each methodClass asString, ' >> ', each selector);
+			onClick: [ self openBrowserOn: each ]] ]
+!
+
+updateSendersList
+	sendersList contents: [ :html |
+	html li
+		class: 'column_label';
+		with: 'Senders (', self senders size asString, ')';
+		style: 'font-weight: bold'.
+	self senders do: [ :each |
+		html li
+			with: (each methodClass asString, ' >> ', each selector);
+			onClick: [ self openBrowserOn: each ]] ]
+! !
+
+!ReferencesBrowser class methodsFor: 'instance creation'!
+
+search: aString
+	^ self new
+		searchReferencesFor: aString;
+		open
+! !
+
+TabWidget subclass: #TestRunner
+	instanceVariableNames: 'selectedCategories packagesList selectedClasses classesList selectedMethods progressBar methodsList result statusDiv'
+	package: 'IDE'!
+
+!TestRunner methodsFor: 'accessing'!
+
+allClasses
+	^ TestCase allSubclasses select: [ :each | each isAbstract not ]
+!
+
+classes
+	^ (self allClasses
+	select: [ :each | self selectedCategories includes: each category ])
+	sort: [ :a :b | a name > b name ]
+!
+
+label
+	^ 'SUnit'
+!
+
+packages
+	| packages |
+	packages := Array new.
+	self allClasses do: [ :each |
+	(packages includes: each category) ifFalse: [
+		packages add: each category ]].
+	^ packages sort
+!
+
+progressBar
+	^ progressBar ifNil: [ progressBar := ProgressBar new ]
+!
+
+result
+	^ result
+!
+
+selectedCategories
+	^ selectedCategories ifNil: [ selectedCategories := Array new ]
+!
+
+selectedClasses
+	^ selectedClasses ifNil: [ selectedClasses := Array new ]
+!
+
+statusInfo
+	^ self printTotal, self printPasses, self printErrors, self printFailures
+!
+
+testCases
+	| testCases |
+	testCases := #().
+	(self selectedClasses
+		select: [ :each | self selectedCategories includes: each category ])
+		do: [ :each | testCases addAll: each buildSuite ].
+	^ testCases
+! !
+
+!TestRunner methodsFor: 'actions'!
+
+performFailure: aTestCase
+	aTestCase runCase
+!
+
+run: aCollection
+| worker |
+	worker := TestSuiteRunner on: aCollection.
+	result := worker result.
+	worker announcer on: ResultAnnouncement do: [ :ann |
+		ann result == result ifTrue: [
+			self progressBar updatePercent: result runs / result total * 100.
+			self updateStatusDiv.
+			self updateMethodsList
+		]
+	].
+	worker run
+!
+
+selectAllCategories
+	self packages do: [ :each |
+		(selectedCategories includes: each) ifFalse: [
+			self selectedCategories add: each ]].
+	self
+		updateCategoriesList;
+		updateClassesList
+!
+
+selectAllClasses
+	self classes do: [ :each |
+		(selectedClasses includes: each) ifFalse: [
+			self selectedClasses add: each ]].
+	self
+		updateCategoriesList;
+		updateClassesList
+!
+
+toggleCategory: aCategory
+	(self isSelectedCategory: aCategory)
+		ifFalse: [ selectedCategories add: aCategory ]
+		ifTrue: [ selectedCategories remove: aCategory ].
+	self
+		updateCategoriesList;
+		updateClassesList
+!
+
+toggleClass: aClass
+	(self isSelectedClass: aClass)
+		ifFalse: [ selectedClasses add: aClass ]
+		ifTrue: [ selectedClasses remove: aClass ].
+	self
+		updateClassesList
+! !
+
+!TestRunner methodsFor: 'initialization'!
+
+initialize
+	super initialize.
+	result := TestResult new
+! !
+
+!TestRunner methodsFor: 'printing'!
+
+printErrors
+	^ self result errors size asString , ' errors, '
+!
+
+printFailures
+	^ self result failures size asString, ' failures'
+!
+
+printPasses
+	^ (self result runs - self result errors size - self result failures size) asString , ' passes, '
+!
+
+printTotal
+	^ self result total asString, ' runs, '
+! !
+
+!TestRunner methodsFor: 'rendering'!
+
+renderBoxOn: html
+	self
+	renderCategoriesOn: html;
+	renderClassesOn: html;
+	renderResultsOn: html
+!
+
+renderButtonsOn: html
+	html button
+	with: 'Run selected';
+	onClick: [ self run: self testCases ]
+!
+
+renderCategoriesOn: html
+	packagesList := html ul class: 'amber_column sunit packages'.
+	self updateCategoriesList
+!
+
+renderClassesOn: html
+	classesList := html ul class: 'amber_column sunit classes'.
+	self updateClassesList
+!
+
+renderErrorsOn: html
+	self result errors do: [ :each |
+		html li
+			class: 'errors';
+			with: each class name, ' >> ', each selector;
+						onClick: [ self performFailure: each ]]
+!
+
+renderFailuresOn: html
+	self result failures do: [ :each |
+		html li
+			class: 'failures';
+			with: each class name, ' >> ', each selector;
+						onClick: [ self performFailure: each ]]
+!
+
+renderResultsOn: html
+	statusDiv := html div.
+	html with: self progressBar.
+	methodsList := html ul class: 'amber_column sunit results'.
+	self updateMethodsList.
+	self updateStatusDiv
+! !
+
+!TestRunner methodsFor: 'testing'!
+
+isSelectedCategory: aCategory
+	^ (self selectedCategories includes: aCategory)
+!
+
+isSelectedClass: aClass
+	^ (self selectedClasses includes: aClass)
+! !
+
+!TestRunner methodsFor: 'updating'!
+
+updateCategoriesList
+	packagesList contents: [ :html |
+		html li
+		class: 'all';
+		with: 'All';
+		onClick: [ self selectAllCategories ].
+	self packages do: [ :each || li |
+		li := html li.
+		(self selectedCategories includes: each) ifTrue: [
+		li class: 'selected' ].
+		li
+		with: each;
+		onClick: [ self toggleCategory: each ]] ]
+!
+
+updateClassesList
+	classesList contents: [ :html |
+	(self selectedCategories isEmpty) ifFalse: [
+		html li
+			class: 'all';
+			with: 'All';
+			onClick: [ self selectAllClasses ]].
+	self classes do: [ :each || li |
+		li := html li.
+		(self selectedClasses includes: each) ifTrue: [
+			li class: 'selected' ].
+		li
+			with: each name;
+			onClick: [ self toggleClass: each ]] ]
+!
+
+updateMethodsList
+	methodsList contents: [ :html |
+		self renderErrorsOn: html.
+				self renderFailuresOn: html ]
+!
+
+updateStatusDiv
+	statusDiv class: 'sunit status ', result status.
+	statusDiv contents: [ :html |
+		html span with: self statusInfo ]
+! !
+
+TabWidget subclass: #Workspace
+	instanceVariableNames: 'sourceArea'
+	package: 'IDE'!
+
+!Workspace methodsFor: 'accessing'!
+
+label
+	^ 'Workspace'
+! !
+
+!Workspace methodsFor: 'actions'!
+
+clearWorkspace
+	sourceArea clear
+!
+
+doIt
+	sourceArea doIt
+!
+
+fileIn
+	sourceArea fileIn
+!
+
+inspectIt
+	sourceArea inspectIt
+!
+
+printIt
+	sourceArea printIt
+!
+
+show
+	super show.
+	sourceArea focus.
+! !
+
+!Workspace methodsFor: 'rendering'!
+
+renderBoxOn: html
+	sourceArea := SourceArea new.
+	sourceArea renderOn: html
+!
+
+renderButtonsOn: html
+	html button
+	with: 'DoIt';
+	title: 'ctrl+d';
+	onClick: [ self doIt ].
+	html button
+	with: 'PrintIt';
+	title: 'ctrl+p';
+	onClick: [ self printIt ].
+	html button
+	with: 'InspectIt';
+	title: 'ctrl+i';
+	onClick: [ self inspectIt ].
+	html button
+	with: 'FileIn';
+	title: 'ctrl+f';
+	onClick: [ self fileIn ].
+	html button
+	with: 'Clear workspace';
+	onClick: [ self clearWorkspace ]
+! !
+
+!AssociativeCollection methodsFor: '*IDE'!
+
+inspectOn: anInspector
+	| variables |
+	variables := Dictionary new.
+	variables at: '#self' put: self.
+	variables at: '#keys' put: self keys.
+	self keysAndValuesDo: [ :key :value |
+		variables at: key put: value ].
+	anInspector
+		setLabel: self printString;
+		setVariables: variables
+! !
+
+!Collection methodsFor: '*IDE'!
+
+inspectOn: anInspector
+	| variables |
+	variables := Dictionary new.
+	variables at: '#self' put: self.
+	self withIndexDo: [ :each :i |
+		variables at: i put: each ].
+	anInspector
+		setLabel: self printString;
+		setVariables: variables
+! !
+
+!Date methodsFor: '*IDE'!
+
+inspectOn: anInspector
+	| variables |
+	variables := Dictionary new.
+	variables at: '#self' put: self.
+	variables at: '#year' put: self year.
+	variables at: '#month' put: self month.
+	variables at: '#day' put: self day.
+	variables at: '#hours' put: self hours.
+	variables at: '#minutes' put: self minutes.
+	variables at: '#seconds' put: self seconds.
+	variables at: '#milliseconds' put: self milliseconds.
+	anInspector
+		setLabel: self printString;
+		setVariables: variables
+! !
+
+!MethodContext methodsFor: '*IDE'!
+
+inspectOn: anInspector
+	| variables |
+	variables := Dictionary new.
+	variables at: '#self' put: self.
+	variables at: '#home' put: self home.
+	variables at: '#receiver' put: self receiver.
+	variables at: '#selector' put: self selector.
+	variables at: '#locals' put: self locals.
+	self class instanceVariableNames do: [ :each |
+		variables at: each put: (self instVarAt: each) ].
+	anInspector
+		setLabel: self printString;
+		setVariables: variables
+! !
+
+!Set methodsFor: '*IDE'!
+
+inspectOn: anInspector
+	| variables i |
+	variables := Dictionary new.
+	variables at: '#self' put: self.
+	i := 1.
+	self do: [ :each |
+		variables at: i put: each.
+		i := i + 1 ].
+	anInspector
+		setLabel: self printString;
+		setVariables: variables
+! !
+
+!String methodsFor: '*IDE'!
+
+inspectOn: anInspector
+	| label |
+	super inspectOn: anInspector.
+	self printString size > 30
+		ifTrue: [ label := (self printString copyFrom: 1 to: 30), '...''' ]
+		ifFalse: [ label := self printString ].
+	anInspector setLabel: label
+! !
+

Some files were not shown because too many files changed in this diff