blog: Google story blog post
@@ -0,0 +1,217 @@
|
||||
---
|
||||
layout: post
|
||||
title: "Why working on Chrome made me develop a tool for reading source code"
|
||||
description: "This post is about how the idea to Coati was born, shows early prototypes and illustrates how the user-centered design process contributed on improving and refining the user interface."
|
||||
author: Eberhard Gräther
|
||||
author-link: http://egraether.com
|
||||
image:
|
||||
feature: post_background.png
|
||||
---
|
||||
|
||||
[Coati](https://coati.io) is a developer tool for fast and efficient source code navigation and exploration. This is the story of how an internship at Google inspired me to start working on a tool for reading source code. I will show early prototypes and explain how the user-centered design process contributed in improving and refining the user interface. This is a rather detailed report. If you prefer a shorter summary, please visit our [front page](https://coati.io).
|
||||
|
||||
# Interning in the Google Chrome Graphics Team
|
||||
|
||||
In fall 2012, after a tedious application process, I turned out to be one of the lucky students to get an internship at Google Mountain View, California. It was the last year of my undergraduate degree at [Salzburg University of Applied Sciences](http://www.fh-salzburg.ac.at/en), where I majored in [game development](https://multimediatechnology.at/). I had worked a lot with computer graphics, was interested in Human Computer Interaction, I knew C++ and JavaScript pretty well, so this internship at the Google Chrome Graphics Team was the perfect fit.
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/chrome_logo.jpg">
|
||||
<img src="../images/story_of_coati/chrome_logo.jpg" alt="">
|
||||
</a>
|
||||
<figcaption>Chrome logo on the wall in front of the office in Mountain View.</figcaption>
|
||||
</figure>
|
||||
|
||||
The first task I got assigned seemed very simple, I almost felt like getting [FizzBuzzed](http://c2.com/cgi/wiki?FizzBuzzTest), but my supervisor assured me that this won't be easy. The graphics team had implemented a frame rate meter for Chromium that shows how often the webpage is repainted. At the time the only way for displaying it was via the command line flag [`--show-fps-counter`](http://peter.sh/experiments/chromium-command-line-switches/#show-fps-counter). My task was adding a checkbox to the settings of the [Chrome DevTools](https://developer.chrome.com/devtools), to make the FPS meter easier to access and also adjustable per tab. I figured out pretty fast in which file I had to add the checkbox and I also knew where in the compositor's HUD-Layer the FPS meter got displayed. All I really needed to do was send a boolean from one place to the other. How hard can it be? I should get this to work in 1-2 hours tops and have it finished within a good workday.
|
||||
|
||||
# Being a Chromium developer
|
||||
|
||||
As you might have already guessed, this took me much longer than I expected. The Chromium codebase is huge and while my supervisor knew a lot about Chromium's compositor, which was the main part the team was working on, he couldn't really tell me much about the DevTools and the relevant parts in-between. He showed me the tools he uses for searching within the code base: [grep](https://www.gnu.org/software/grep/manual/grep.html), [git-grep](https://git-scm.com/docs/git-grep) and [Chromium Code Search](https://cs.chromium.org/), an online source explorer where the whole Chromium codebase is indexed.
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/lost_connection.png">
|
||||
<img src="../images/story_of_coati/lost_connection.png" alt="">
|
||||
</a>
|
||||
</figure>
|
||||
|
||||
I realized pretty quickly that I had not the slightest chance of comprehending Chromium's massive architecture. The documentation was not really helpful, as most of it was too high-level for my usecase. I also learned that although the developers of the team were very friendly, they are not too excited about constantly getting interrupted by some intern asking about the codebase. So I spent most of my time on reading source code and drawing scribbles of how classes are composed and where certain methods get called.
|
||||
|
||||
After around 2-3 days I finally had a very hacky implementation working. I didn't bother about thread synchronisation, removed const at a couple places and didn't know that I actually worked on two code bases at once, being [Chromium](https://www.chromium.org/Home) and [WebKit](https://webkit.org/) (now [Blink](http://www.chromium.org/blink)). After some initial feedback from my supervisor, the code review process started and after I rewrote the whole implementation twice, I could finally land the two patches ([1](https://codereview.chromium.org/11189037/), [2](https://bugs.webkit.org/show_bug.cgi?id=99660)) and finish my task. In the end the whole process lasted about one month.
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/fps_meter_new.png">
|
||||
<img src="../images/story_of_coati/fps_meter_new.png" alt="">
|
||||
</a>
|
||||
<figcaption>The checkbox in Chrome's DevTools for toggling the FPS meter.</figcaption>
|
||||
</figure>
|
||||
|
||||
# Software developers spend more time reading than writing source code
|
||||
|
||||
In the next meeting my supervisor congratulated me for my great work. I was baffled. To me this whole task took way too long. I spent roughly 95% of my time reading source code. That's not productive I said and asked him how I could improve. He calmed me down and told me that I was actually much faster than he expected. He assumed this task would take up my whole three month internship. I was surprised to hear that. Technically I wrote less than one line of code per hour of work time, which did not sound very productive. "Look around" he said, "everyone in here is reading source code most of their time. That's part of the job on such a big software project. It takes about two months for a new developer to actually become productive here."
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/pie_chart.png">
|
||||
<img src="../images/story_of_coati/pie_chart.png" alt="">
|
||||
</a>
|
||||
<figcaption>What developers spend their time on (chart based on <a href="https://blog.codinghorror.com/when-understanding-means-rewriting/">"When Understanding means Rewriting"</a>)</figcaption>
|
||||
</figure>
|
||||
|
||||
This was completely new to me at the time, but it turns out that it's a common known fact among software developers, that more time is spent reading than actually writing source code. Peter Hallam wrote a [blog post](https://blogs.msdn.microsoft.com/peterhal/2006/01/04/what-do-programmers-really-do-anyway-aka-part-2-of-the-yardstick-saga/) about this and argues that roughly 70-78% of a software developer's time is spent on understanding the existing implementation. This inspired Jeff Atwood to write a [post on Coding Horror](https://blog.codinghorror.com/when-understanding-means-rewriting/) that further questions whether a developer should read source code at all, or just start rewriting from scratch. Since rewriting is not really an option for new developers on Chromium, the only option is reading source code.
|
||||
|
||||
# How do you read source code?
|
||||
|
||||
If so much time is spent on reading source code, what tools are available for this task? I started asking developers on the team and friends from university how they read code (There are also threads on [Hacker News](https://news.ycombinator.com/) once in a while regarding this topic: [1](https://news.ycombinator.com/item?id=9784008), [2](https://news.ycombinator.com/item?id=8263402)). It turns out there is no common strategy for exploring source code. Some developers use grep, some a debugger, others draw diagrams. Most of them just use their source code editor and whatever features it offers. But while source code editors are great for efficiently writing source code, they are not made for quickly retrieving information about the implementation.
|
||||
|
||||
Chromium Code Search is a big step in the right direction. By showing all occurences of a certain symbol, it already offers more functionality than most developer tools. But you still need to figure out what relationships a symbol has to other symbols by reading each line where the symbol appears. Programming languages are designed to be dense and expressive, which makes it hard to detect information at a glance. As a software developer you always have to deal with all the details of the source code. You spend your time with going from file to file searching for small pieces of information and slowly build up the mental model of a code path.
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/mental_model.png">
|
||||
<img src="../images/story_of_coati/mental_model.png" alt="">
|
||||
</a>
|
||||
<figcaption>Building up a mental model while reading source code takes time.</figcaption>
|
||||
</figure>
|
||||
|
||||
I started to observe myself while reading source code. What are the things I'm usually interested in when looking at a class or a function? Most of the time I just wanted to know very simple things. Where is a class instantiated? Which classes implement a certain interface? Where is this method called? Finding this information by reading lines and lines of source code takes a lot of time. The computer knows how the programming language works and thereby already knows where and how all symbols are used within the whole codebase. Why can't I just ask it those questions? Why can't I just enter a search query for whatever I wanted to know and have everything laid out in front of me?
|
||||
|
||||
# Visual Navigation through Static Analysis
|
||||
|
||||
After a couple of weeks I came up with an idea to address this problem: interactive visualization of the source code's structure. This idea was not really new, I later even learned it was almost as old as programming. I imagined a tool that statically analyzes the source code and thereby figures out which symbols exist and how they relate to each other. This semantic information is then used to create a graph visualization with symbols as nodes and relationships as edges. The visualization is placed next to the source code like a map. By clicking on any node or edge you could instantly see to which line in the source code it belongs. This would allow you to quickly get an overview of all existing symbols, while still being able to access all the details of the implementation. Super simple!
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/mental_idea.png">
|
||||
<img src="../images/story_of_coati/mental_idea.png" alt="">
|
||||
</a>
|
||||
<figcaption>A visual representation of the source code's structure offloads your brain.</figcaption>
|
||||
</figure>
|
||||
|
||||
I kept this idea in mind and talked to some people about it, which produced mixed results. During my internship I continued to work on Chromium's developer tools, I got to know the DevTools and DevRel teams, and also authored an article on the [developer blog](https://developers.google.com/web/updates/2013/02/Profiling-Long-Paint-Times-with-DevTools-Continuous-Painting-Mode). I am very happy that I had this opportunity to work in a highly professional environment at Google, where I learned a lot about writing robust and maintainable code.
|
||||
|
||||
# Research on Software Visualization
|
||||
|
||||
I returned to Salzburg in order to finish my undergraduate degree. Part of it was writing a thesis. I was free to choose any topic, so I decided to work on my idea. I wanted to create a prototype and test it on a few participants in a small qualitative user study. At the time I had already some experience in the field of Human Computer Interaction due to an earlier internship at the [RMIT Exertion Games Lab](http://exertiongameslab.org/), so I was well prepared for doing some research.
|
||||
|
||||
I started by reading a couple of books and papers on visualization methods, human visual perception and the history of software visualization. I still remember how I came across one paragraph, that I found especially intriguing. It gives a pretty simple explanation on why software visualization is not widely used within computer science yet:
|
||||
|
||||
> "Visualization is heavily used in mechanical engineering, chemistry, physics, and medicine. Computer scientists have developed sophisticated systems to produce visualizations for these disciplines. Astonishingly enough, computer scientists have only made little use of visualization as a tool for designing, implementing and maintaining software. Even worse, many consider themselves as theoreticians and disregard visualization – an etymologically wrong dichotomy. Programmers tend to adapt to the level of representation provided by the computer, instead of adapting the computers representations to their perceptive abilities."
|
||||
([Dhiel 2007, 2](http://www.springer.com/in/book/9783540465041))
|
||||
|
||||
# A first interactive prototype
|
||||
|
||||
I didn't actually implement any static source code analysis for my first prototype. I just created a simple Tic-Tac-Toe game in C++ and analyzed it manually. The prototype was built in JavaScript with [Raphaël](https://dmitrybaranovskiy.github.io/raphael/) and [Syntax Highlighter](http://alexgorbatchev.com/SyntaxHighlighter/). It featured an interactive graph visualization next to a simple code view. The graph visualization was more or less designed after the renown Visual Information Seeking Mantra, which stayed a guiding principle for the user interface design of Coati:
|
||||
|
||||
> “Overview first, zoom and filter, then details-on-demand”
|
||||
([Shneiderman 1996](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=545307))
|
||||
|
||||
The graph visualization showed all the symbols of the project and their relationships. When clicking any node the corresponding declaration of that symbol is shown in the code view. Same for edges and their corresponding statements. Class nodes initially hide their members and can be expanded by clicking the ellipsis (...).
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/prototype1.png">
|
||||
<img src="../images/story_of_coati/prototype1.png" alt="">
|
||||
</a>
|
||||
<figcaption>Image of the first prototype. Different node and edge types were displayed with different shapes.</figcaption>
|
||||
</figure>
|
||||
|
||||
The prototype had some obvious flaws, but it was good enough for fulfilling its one purpose: To test whether an interactive visualization can help in understanding source code. After three years of iterating and polishing, this original prototype has almost nothing to do with how Coati works today. However, if you want to take a look, I made it available [here](../media/prototype_one/).
|
||||
|
||||
# Most important: Talk to your Users
|
||||
|
||||
My user study had twelve participants, all more or less experienced software developers. I started by asking them about their workflow and what tools they use. After I explained them how to use my prototype, the main part of the study began. Participants had to retrieve information from the Tic-Tac-Toe game's source code by picking questions like:
|
||||
|
||||
* Which classes derive from the class Player?
|
||||
* What is the purpose of the member Field::grid_?
|
||||
* Why does the game restart after a round is finished?
|
||||
|
||||
(We still use these questions in our [Coati trial challenge](https://www.coati.io/trial) and the Tic-Tac-Toe source code comes with every download.)
|
||||
|
||||
Some of these questions were easy to solve with the prototype, others were hard. The participants could only use the limited functionality the prototype offered. I urged them to [think aloud](https://en.wikipedia.org/wiki/Think_aloud_protocol) while solving the questions. The study ended with a short open interview to gather feedback, which resulted in some very important insights:
|
||||
|
||||
* Participants reported that the graph visualization did indeed help in answering some questions, but it got very confusing as soon as there were too many classes expanded.
|
||||
* I noticed that some participants tried clicking symbols in the code view as well, others suggested it during the feedback interview.
|
||||
* Some participants were looking for a search feature or later proposed that it should be possible to somehow find every symbol.
|
||||
* Most participants had experienced being lost in source code themselves at one point and stated that they would be happy about a properly working tool of that kind.
|
||||
|
||||
# Finding the team and a place to work
|
||||
|
||||
Alright, this was getting interesting. How can I create this tool properly? The master's degree that continues my undergraduate degree allows students to work on a big two year project. This was perfect. I had some friends that also continued with a master's degree, so it was not to hard to get a team of four software engineers together. Eventually we also found a graphic designer. The university even gave us a small project room, that we could use for working between our courses.
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/pixel_team.png">
|
||||
<img src="../images/story_of_coati/pixel_team.png" alt="">
|
||||
</a>
|
||||
<figcaption>Team Coati.</figcaption>
|
||||
</figure>
|
||||
|
||||
# The next iteration: Search, Graph, Code
|
||||
|
||||
Drawing from the feedback of the first user study we went back to the whiteboard and rethought the concept. We designed and developed another prototype, with some key improvements to the first one:
|
||||
|
||||
* Symbols could be activated to show all relevant information in each view.
|
||||
* Every symbol could be found and activated via a small search field with auto completions.
|
||||
* The graph visualization only showed the active symbol and all relationships it has to other symbols.
|
||||
* Lines in the code view could be clicked to activate symbols.
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/prototype2.png">
|
||||
<img src="../images/story_of_coati/prototype2.png" alt="">
|
||||
</a>
|
||||
<figcaption>Image of the second prototype. It had a search field with autocompletions and an interactive code view.</figcaption>
|
||||
</figure>
|
||||
|
||||
If you want to test the second prototype, I also made it available [here](../media/prototype_two/).
|
||||
|
||||
We conducted another user study with this refined prototype and yielded much better feedback. This time the participants really saw a big benefit in a tool like this. They still demanded more features, but we had our proof of concept. Our tool will consist of three main components:
|
||||
|
||||
* **search field** for finding symbols
|
||||
* **graph visualization** for exploring the relationships
|
||||
* **code view** for all the details of the implementation
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/concept.png">
|
||||
<img src="../images/story_of_coati/concept.png" alt="">
|
||||
</a>
|
||||
<figcaption>Coati concept scribble showing the three main components: search, code, graph.</figcaption>
|
||||
</figure>
|
||||
|
||||
# Developing with C++ and Clang
|
||||
|
||||
Before we could actually start working, we had to take a careful look around and check whether our conceptualized tool did not exist already. We looked into all kinds of developer tools like IDEs, UML tools, documentation software, plugins, extensions and even visual programming languages. We found a lot of tools based on static analysis, some using visualization, some having autocompletions, but nothing that really put all these great features together into one simple user interface. We defined key aspects that were important to us and also set Coati apart from other tools:
|
||||
|
||||
* **simple**: Every developer should be able to pick it up and start using in a couple of minutes.
|
||||
* **independent**: It shouldn't matter what platform or tools a developer already uses.
|
||||
* **fast**: It should be highly responsive without waiting times for results.
|
||||
* **offline**: There shouldn't be a need to upload source code or having a constant connection to the internet.
|
||||
* **companion**: It should expand the tool chain of a developer, without replacing any tool. There are already lots of great source code editors out there, there is no need of building another one. Instead we allowed Coati to communicate with source code editors, please have a look at our [plugins](https://www.coati.io/documentation/#CODEEDITORPLUGINS).
|
||||
|
||||
One of the bigger open questions was which programming language to write our tool in and which ones to support. Since static analysis doesn't work equally well on every language, we had to choose a typed language. We decided in favor of C++. C++ is fast, works well on cross-platform, has good cross-platform libraries, is widely used in application development and we knew it pretty well ourselves. We used [Clang LibTooling](http://clang.llvm.org/docs/LibTooling.html) for our static analysis, which also allowed us to easily support both C and C++. If you are Clang developer and you want to use Coati on Clang, please read our [recent blog post](https://www.coati.io/blog/indexing_clang_with_coati_using_clang/).
|
||||
|
||||
We are already expanding our language support and will soon also offer Java. We should have a build for testing available soon. If you want to become a Coati tester for Java, please write an e-mail at [mail@coati.io](mailto:mail@coati.io?Subject=Java%20tester) with subject "Java tester".
|
||||
|
||||
# Making Coati available to developers
|
||||
|
||||
Fast forward two years. We didn't want our project to go to waste after our master's degree finished, so we decided to keep at it. By now Coati has become a small startup and we are working on making a living with our tool. We are a happy member of the [FH-Startup center](http://www.fh-salzburg.ac.at/fhstartup/ziele-mission/), received funding by the [Austria Wirtschaftsservice](http://awsg.at/Content.Node/en/index.en.php) and were recently accepted to the new [Startup Salzburg Factory](http://www.startup-salzburg.at/en/startup-services/startup-salzburg-factory/) incubator.
|
||||
|
||||
Our website launched in spring, which marked the start of our public beta. We currently offer Coati as pre-release version Coati 0. Licences are still available at an [early-bird rate](https://coati.io/buy-license), but won't be for much longer. During the last weeks, our first customers have helped us a lot in adapting Coati to the requirements of real world software development. They have also demanded lots of new UI features, more than we currently find time to implement.
|
||||
|
||||
<figure>
|
||||
<a href="../images/story_of_coati/full.png">
|
||||
<img src="../images/story_of_coati/full.png" alt="">
|
||||
</a>
|
||||
<figcaption>Coati's current user interface displaying the Tic-Tac-Toe game from the prototypes.</figcaption>
|
||||
</figure>
|
||||
|
||||
By now, I have been using Coati for my development work for more than half a year and it greatly influenced my workflow. At first I only used it occasionally, when I really had trouble understanding what one of my colleagues wrote. Now I have Coati constantly open on my second screen and use it for most quick look-ups on the codebase. I guess I already crossed the point of no return.
|
||||
|
||||
Among other things I use Coati for:
|
||||
|
||||
* Inspecting the implementation when I start a new task.
|
||||
* Exploring dependencies between types and functions.
|
||||
* Finding where an interface is implemented and which methods get overridden.
|
||||
* Following code paths from method to method.
|
||||
* Figuring out what can be simplified or removed when refactoring.
|
||||
|
||||
Read more about Coati's features on our [front page](https://www.coati.io/#how-it-works).
|
||||
|
||||
Coati has also simplified the communication within our development team. Before Coati, we often spent lots of time arguing about what side-effects changing a certain implementation might have. Now we just look at the problem with Coati and immediately see if problems arise. Coati allows us to see our code base from a bird's-eye view, which makes it easy to explore all symbols and their dependencies.
|
||||
|
||||
Over the past months Coati has become a big [time saver](https://xkcd.com/1205/) for us. I'm proud of what we have accomplished already and I'm excited for some great features just waiting to be implemented. That was my story on Coati, I hope you enjoyed it!
|
||||
|
||||
If you want to take a look at Coati's user interface now, go ahead and download our [trial](https://www.coati.io/trial). We are happy if you leave a comment!
|
||||
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 95 KiB |
|
After Width: | Height: | Size: 254 KiB |
|
After Width: | Height: | Size: 261 KiB |
|
After Width: | Height: | Size: 416 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 92 KiB |
|
After Width: | Height: | Size: 91 KiB |
|
After Width: | Height: | Size: 116 KiB |
|
After Width: | Height: | Size: 261 KiB |
|
After Width: | Height: | Size: 290 KiB |
|
After Width: | Height: | Size: 392 KiB |
@@ -0,0 +1,79 @@
|
||||
data.push( { type : 'file', name : 'computer.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 6, type : 'class', name : 'ArtificialPlayer', base : 'Player', content : {
|
||||
public : [
|
||||
{ line : 8, type : 'method', name : 'ArtificialPlayer', params : [ 'Field::Token', 'std::string' ], content : [
|
||||
{ line : 9, type : 'call', class : 'Player', method : 'Player' }
|
||||
]},
|
||||
|
||||
{ line : 12, type : 'method', name : 'Turn', abstraction : 'virtual', return : 'Field::Move', params : [ 'Field' ], content : [
|
||||
{ line : 13, type : 'call', function : 'srand' }, { line : 13, type : 'call', function : 'time' },
|
||||
{ line : 14, type : 'call', class : 'Field', method : 'Clone' },
|
||||
{ line : 15, type : 'use', class : 'ArtificialPlayer::Node' }, { line : 15, type : 'call', method : 'MinMax' }, { line : 15, type : 'use', member : 'token_' },
|
||||
{ line : 16, type : 'use', class : 'ArtificialPlayer::Node', member : 'move' }
|
||||
]},
|
||||
|
||||
], private : [
|
||||
{ line : 20, type : 'class', name : 'Node', content : { public : [
|
||||
{ line : 21, type : 'member', name : 'move', class : 'Field::Move' },
|
||||
{ line : 22, type : 'member', name : 'value', class : 'int' }
|
||||
]}
|
||||
},
|
||||
{ line : 25, type : 'method', name : 'MinMax', return : 'Node', params : [ 'Field', 'Field::Token' ], content : [
|
||||
{ line : 26, type : 'use', class : 'Node' },
|
||||
|
||||
|
||||
{ line : 29, type : 'use', class : 'Move' },
|
||||
|
||||
|
||||
|
||||
{ line : 33, type : 'use', class : 'Move', member : 'row' },
|
||||
|
||||
|
||||
{ line : 36, type : 'use', class : 'Move', member : 'col' },
|
||||
|
||||
{ line : 38, type : 'call', class : 'Field', method : 'IsEmpty' },
|
||||
|
||||
|
||||
|
||||
{ line : 42, type : 'call', class : 'Field', method : 'MakeMove' },
|
||||
|
||||
{ line : 44, type : 'call', method : 'Evaluate' },
|
||||
{ line : 45, type : 'call', class : 'Field', method : 'IsFull' },
|
||||
{ line : 46, type : 'call', method : 'MinMax' }, { line : 46, type : 'call', class : 'Field', method : 'Opponent' }, { line : 46, type : 'use', class : 'Node', member : 'value' },
|
||||
|
||||
|
||||
{ line : 49, type : 'call', class : 'Field', method : 'ClearMove' },
|
||||
|
||||
{ line : 51, type : 'use', class : 'Node', member : 'value' },
|
||||
{ line : 52, type : 'use', class : 'Node', member : 'move' },
|
||||
{ line : 53, type : 'use', class : 'Node', member : 'value' },
|
||||
{ line : 54, type : 'use', class : 'Node', member : 'value' },
|
||||
|
||||
|
||||
{ line : 57, type : 'call', function : 'rand' },
|
||||
{ line : 58, type : 'use', class : 'Node', member : 'move' },
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
]},
|
||||
|
||||
{ line : 67, type : 'method', name : 'Evaluate', return : 'int', params : [ 'Field', 'Field::Token' ], content : [
|
||||
{ line : 68, type : 'call', class : 'Field', method : 'SameInRow' },
|
||||
|
||||
{ line : 70, type : 'call', class : 'Field', method : 'SameInRow' }, { line : 70, type : 'call', class : 'Field', method : 'Opponent' },
|
||||
|
||||
{ line : 72, type : 'call', class : 'Field', method : 'SameInRow' }
|
||||
|
||||
|
||||
|
||||
]}
|
||||
]}
|
||||
}
|
||||
]});
|
||||
@@ -0,0 +1,147 @@
|
||||
data.push( { type : 'file', name : 'field.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 7, type : 'class', name : 'Field', content : {
|
||||
public : [
|
||||
{ line : 9, type : 'class', name : 'Token', content : { public : [
|
||||
{ line : 10, type : 'member', name : 'None' },
|
||||
{ line : 11, type : 'member', name : 'PlayerA' },
|
||||
{ line : 12, type : 'member', name : 'PlayerB' }
|
||||
]}},
|
||||
|
||||
{ line : 15, type : 'method', name : 'Opponent', abstraction : 'static', return : 'Token', params : [ 'Token' ], content : [
|
||||
{ line : 16, type : 'call', function : 'assert' }, { line : 16, type : 'use', class : 'Token', member : 'None' },
|
||||
{ line : 17, type : 'use', class : 'Token', member : 'PlayerA' },
|
||||
{ line : 18, type : 'use', class : 'Token', member : 'PlayerB' },
|
||||
|
||||
{ line : 20, type : 'use', class : 'Token', member : 'PlayerA' }
|
||||
|
||||
]},
|
||||
|
||||
{ line : 24, type : 'class', name : 'Move', content : { public : [
|
||||
{ line : 25, type : 'member', name : 'row', class : 'int' },
|
||||
{ line : 26, type : 'member', name : 'col', class : 'int' }
|
||||
]}},
|
||||
|
||||
{ line : 29, type : 'method', name : 'Field', content : [
|
||||
{ line : 30, type : 'use', member : 'left_' },
|
||||
{ line : 31, type : 'use', member : 'grid_' }, { line : 31, type : 'use', class : 'Token' },
|
||||
|
||||
{ line : 33, type : 'use', member : 'grid_' }, { line : 33, type : 'use', class : 'Token' },
|
||||
|
||||
]},
|
||||
|
||||
{ line : 37, type : 'method', name : '~Field', content : [
|
||||
|
||||
{ line : 39, type : 'use', member : 'grid_' },
|
||||
|
||||
{ line : 41, type : 'use', member : 'grid_' },
|
||||
]},
|
||||
|
||||
{ line : 44, type : 'method', name : 'Clone', return : 'Field', content : [
|
||||
|
||||
|
||||
|
||||
{ line : 48, type : 'use', member : 'grid_' }, { line : 48, type : 'use', member : 'grid_' },
|
||||
|
||||
|
||||
{ line : 51, type : 'use', member : 'left_' }, { line : 51, type : 'use', member : 'left_' }
|
||||
]},
|
||||
|
||||
|
||||
{ line : 55, type : 'method', name : 'Clear', content : [
|
||||
|
||||
|
||||
{ line : 58, type : 'use', member : 'grid_' }, { line : 58, type : 'use', class : 'Token', member : 'None' },
|
||||
|
||||
|
||||
{ line : 61, type : 'use', member : 'left_' }
|
||||
]},
|
||||
|
||||
{ line : 64, type : 'method', name : 'Show', content : [
|
||||
{ line : 65, type : 'use', class : 'std::cout' },
|
||||
|
||||
{ line : 67, type : 'use', class : 'std::cout' },
|
||||
|
||||
|
||||
{ line : 70, type : 'use', member : 'grid_' }, { line : 70, type : 'use', class : 'Token', member : 'PlayerA' },
|
||||
{ line : 71, type : 'use', class : 'std::cout' },
|
||||
{ line : 72, type : 'use', member : 'grid_' }, { line : 71, type : 'use', class : 'Token', member : 'PlayerA' },
|
||||
{ line : 73, type : 'use', class : 'std::cout' },
|
||||
|
||||
{ line : 75, type : 'use', class : 'std::cout' },
|
||||
|
||||
|
||||
|
||||
{ line : 79, type : 'use', class : 'std::cout' },
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 84, type : 'use', class : 'std::cout' },
|
||||
|
||||
|
||||
{ line : 87, type : 'use', class : 'std::cout' }
|
||||
]},
|
||||
|
||||
{ line : 90, type : 'method', name : 'SameInRow', return : 'int', params : [ 'Token', 'int' ], content : [
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 95, type : 'use', member : 'grid_' }, { line : 95, type : 'use', member : 'grid_' }, { line : 95, type : 'use', member : 'grid_' },
|
||||
|
||||
{ line : 97, type : 'use', member : 'grid_' }, { line : 97, type : 'use', member : 'grid_' }, { line : 97, type : 'use', member : 'grid_' },
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 102, type : 'use', member : 'grid_' }, { line : 102, type : 'use', member : 'grid_' }, { line : 102, type : 'use', member : 'grid_' },
|
||||
|
||||
{ line : 104, type : 'use', member : 'grid_' }, { line : 104, type : 'use', member : 'grid_' }, { line : 104, type : 'use', member : 'grid_' },
|
||||
|
||||
|
||||
|
||||
|
||||
]},
|
||||
|
||||
{ line : 111, type : 'method', name : 'InRange', return : 'bool', params : [ 'Move' ], content : [
|
||||
{ line : 112, type : 'use', class : 'Move', member : 'row' }, { line : 112, type : 'use', class : 'Move', member : 'row' }, { line : 112, type : 'use', class : 'Move', member : 'col' }, { line : 112, type : 'use', class : 'Move', member : 'col' }
|
||||
]},
|
||||
|
||||
{ line : 115, type : 'method', name : 'IsEmpty', return : 'bool', params : [ 'Move' ], content : [
|
||||
{ line : 116, type : 'use', member : 'grid_' }, { line : 116, type : 'use', class : 'Move', member : 'row' }, { line : 116, type : 'use', class : 'Move', member : 'col' }, { line : 116, type : 'use', class : 'Token', member : 'None' }
|
||||
]},
|
||||
|
||||
{ line : 119, type : 'method', name : 'IsFull', return : 'bool', content : [
|
||||
{ line : 120, type : 'use', member : 'left_' }
|
||||
]},
|
||||
|
||||
{ line : 123, type : 'method', name : 'MakeMove', params : [ 'Move', 'Token' ], content : [
|
||||
{ line : 124, type : 'call', function : 'assert' }, { line : 124, type : 'call', method : 'InRange' },
|
||||
{ line : 125, type : 'call', function : 'assert' }, { line : 125, type : 'call', method : 'IsEmpty' },
|
||||
{ line : 126, type : 'call', function : 'assert' }, { line : 126, type : 'use', class : 'Token', member : 'None' },
|
||||
{ line : 127, type : 'call', function : 'assert' }, { line : 127, type : 'use', member : 'left_' },
|
||||
|
||||
{ line : 129, type : 'use', member : 'grid_' }, { line : 129, type : 'use', class : 'Move', member : 'row' }, { line : 129, type : 'use', class : 'Move', member : 'row' },
|
||||
{ line : 130, type : 'use', member : 'left_' },
|
||||
]},
|
||||
|
||||
{ line : 133, type : 'method', name : 'ClearMove', params : [ 'Move' ], content : [
|
||||
{ line : 134, type : 'call', function : 'assert' }, { line : 134, type : 'call', method : 'InRange' },
|
||||
{ line : 135, type : 'call', function : 'assert' }, { line : 135, type : 'call', method : 'IsEmpty' },
|
||||
{ line : 136, type : 'call', function : 'assert' }, { line : 136, type : 'use', member : 'left_' },
|
||||
|
||||
{ line : 138, type : 'use', member : 'grid_' }, { line : 138, type : 'use', class : 'Move', member : 'row' }, { line : 138, type : 'use', class : 'Move', member : 'row' }, { line : 138, type : 'use', class : 'Token', member : 'None' },
|
||||
{ line : 139, type : 'use', member : 'left_' },
|
||||
]}
|
||||
|
||||
], private : [
|
||||
{ line : 143, type : 'member', name : 'grid_', class : 'Token' },
|
||||
{ line : 144, type : 'member', name : 'left_', class : 'int' }
|
||||
]}
|
||||
}
|
||||
]});
|
||||
@@ -0,0 +1,50 @@
|
||||
data.push( { type : 'file', name : 'human.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 7, type : 'class', name : 'HumanPlayer', base : 'Player', content : {
|
||||
public : [
|
||||
{ line : 9, type : 'method', name : 'HumanPlayer', params : [ 'Field::Token', 'std::string' ], content : [
|
||||
{ line : 10, type : 'call', class : 'Player', method : 'Player' }
|
||||
]},
|
||||
|
||||
{ line : 13, type : 'method', name : 'Turn', abstraction : 'virtual', return : 'Field::Move', params : [ 'Field' ], content : [
|
||||
|
||||
{ line : 15, type : 'use', class : 'std::cout' },
|
||||
|
||||
{ line : 17, type : 'call', method : 'Input' },
|
||||
{ line : 18, type : 'use', class : 'Move', member : 'row' },
|
||||
{ line : 19, type : 'use', class : 'Move', member : 'col' },
|
||||
{ line : 20, type : 'call', method : 'Check' }
|
||||
|
||||
]},
|
||||
|
||||
], private : [
|
||||
{ line : 25, type : 'method', name : 'Input', return : 'Field::Move', content : [
|
||||
{ line : 26, type : 'use', class : 'Move' },
|
||||
|
||||
{ line : 28, type : 'use', class : 'std::cout' },
|
||||
{ line : 29, type : 'call', function : 'input::number' }, { line : 29, type : 'use', class : 'Move', member : 'row' },
|
||||
|
||||
{ line : 31, type : 'use', class : 'std::cout' },
|
||||
{ line : 32, type : 'call', function : 'input::number' }, { line : 32, type : 'use', class : 'Move', member : 'col' },
|
||||
|
||||
{ line : 34, type : 'use', class : 'std::cout' }
|
||||
|
||||
]},
|
||||
|
||||
{ line : 38, type : 'method', name : 'Check', return : 'bool', params : [ 'Field', 'Field::Move' ], content : [
|
||||
{ line : 39, type : 'call', class : 'Field', method : 'InRange' },
|
||||
{ line : 40, type : 'use', class : 'std::cout' },
|
||||
|
||||
{ line : 42, type : 'call', class : 'Field', method : 'IsEmpty' },
|
||||
{ line : 43, type : 'use', class : 'std::cout' }
|
||||
|
||||
|
||||
|
||||
]}
|
||||
]}
|
||||
}
|
||||
]});
|
||||
@@ -0,0 +1,20 @@
|
||||
data.push( { type : 'file', name : 'input.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 11, type : 'function', name : 'input::number', return : 'bool', content : [
|
||||
{ line : 12, type : 'use', class : 'std::string'},
|
||||
{ line : 13, type : 'call', function : 'getline'}, { line : 13, type : 'use', class : 'std::cin'},
|
||||
{ line : 14, type : 'use', class : 'std::stringstream'}
|
||||
|
||||
]}
|
||||
|
||||
|
||||
|
||||
]});
|
||||
@@ -0,0 +1,11 @@
|
||||
data.push( { type : 'file', name : 'main.cpp', content : [
|
||||
|
||||
{ line : 3, type : 'function', name : 'main', return : 'int', content : [
|
||||
{ line : 4, type : 'call', class : 'TicTacToe', method : 'TicTacToe' },
|
||||
|
||||
{ line : 6, type : 'call', class : 'TicTacToe', method : 'Start' },
|
||||
{ line : 7, type : 'call', class : 'TicTacToe', method : 'Run' }
|
||||
|
||||
|
||||
]}
|
||||
]});
|
||||
@@ -0,0 +1,21 @@
|
||||
data.push( { type : 'file', name : 'player.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 8, type : 'class', name : 'Player', content : {
|
||||
public : [
|
||||
{ line : 10, type : 'method', name : 'Player', params : [ 'Field::Token', 'std::string' ], content : [
|
||||
{ line : 11, type : 'use', member : 'token_' },
|
||||
{ line : 12, type : 'use', member : 'name_' }
|
||||
]},
|
||||
|
||||
{ line : 15, type : 'method', name : 'Turn', abstraction : 'pure_virtual', return : 'Field::Move', params : [ 'Field' ] },
|
||||
|
||||
{ line : 17, type : 'member', name : 'token_', class : 'Field::Token' },
|
||||
{ line : 18, type : 'member', name : 'name_', class : 'std::string' },
|
||||
]}
|
||||
}
|
||||
]});
|
||||
@@ -0,0 +1,93 @@
|
||||
data.push( { type : 'file', name : 'tictactoe.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 10, type : 'class', name : 'TicTacToe', content : {
|
||||
public : [
|
||||
{ line : 12, type : 'method', name : 'TicTacToe', content : [
|
||||
{ line : 13, type : 'use', member : 'players_' },
|
||||
{ line : 14, type : 'use', member : 'players_' }
|
||||
]},
|
||||
|
||||
{ line : 17, type : 'method', name : '~TicTacToe', content : [
|
||||
{ line : 18, type : 'call', method : 'Reset' }
|
||||
]},
|
||||
|
||||
{ line : 21, type : 'method', name : 'Start', return : 'bool', content : [
|
||||
{ line : 22, type : 'call', method : 'Reset' },
|
||||
{ line : 23, type : 'use', class : 'std::cout' },
|
||||
|
||||
{ line : 25, type : 'use', member : 'players_' }, { line : 25, type : 'call', method : 'SelectPlayer' }, { line : 25, type : 'use', class : 'Field::Token', member : 'PlayerA' },
|
||||
{ line : 26, type : 'use', member : 'players_' },
|
||||
|
||||
|
||||
|
||||
{ line : 30, type : 'use', member : 'players_' }, { line : 30, type : 'call', method : 'SelectPlayer' }, { line : 30, type : 'use', class : 'Field::Token', member : 'PlayerB' },
|
||||
{ line : 31, type : 'use', member : 'players_' },
|
||||
|
||||
|
||||
|
||||
{ line : 35, type : 'use', class : 'std::cout' },
|
||||
|
||||
]},
|
||||
|
||||
{ line : 39, type : 'method', name : 'Run', content : [
|
||||
{ line : 40, type : 'use', member : 'field_' }, { line : 40, type : 'call', method : 'Show', class : 'Field' },
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 45, type : 'use', member : 'players_' },
|
||||
|
||||
{ line : 47, type : 'use', member : 'field_' }, { line : 47, type : 'call', method : 'MakeMove', class : 'Field' }, { line : 47, type : 'call', method : 'Turn', class : 'Player' }, { line : 47, type : 'use', member : 'token_', class : 'Player' },
|
||||
{ line : 48, type : 'use', member : 'field_' }, { line : 48, type : 'call', method : 'Show', class : 'Field' },
|
||||
|
||||
{ line : 50, type : 'use', member : 'field_' }, { line : 50, type : 'call', method : 'SameInRow', class : 'Field' }, { line : 50, type : 'use', member : 'token_', class : 'Player' },
|
||||
{ line : 51, type : 'use', class : 'std::cout' }, { line : 51, type : 'use', member : 'name_', class : 'Player' },
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 58, type : 'use', class : 'std::cout' }
|
||||
]},
|
||||
|
||||
], private : [
|
||||
{ line : 62, type : 'method', name : 'Reset', content : [
|
||||
{ line : 63, type : 'use', member : 'field_' }, { line : 63, type : 'call', method : 'Clear', class : 'Field' },
|
||||
|
||||
|
||||
{ line : 66, type : 'use', member : 'players_' },
|
||||
{ line : 67, type : 'use', member : 'players_' },
|
||||
{ line : 68, type : 'use', member : 'players_' }
|
||||
|
||||
|
||||
]},
|
||||
|
||||
{ line : 73, type : 'method', name : 'SelectPlayer', return : 'Player', params : [ 'Field::Token', 'std::string' ], content : [
|
||||
|
||||
|
||||
|
||||
{ line : 77, type : 'use', class : 'std::cout' },
|
||||
{ line : 78, type : 'call', function : 'input::number' },
|
||||
|
||||
|
||||
{ line : 81, type : 'call', method : 'HumanPlayer', class : 'HumanPlayer' },
|
||||
{ line : 82, type : 'call', method : 'ArtificialPlayer', class : 'ArtificialPlayer' },
|
||||
|
||||
{ line : 84, type : 'use', class : 'std::cout' }
|
||||
|
||||
|
||||
]},
|
||||
|
||||
{ line : 89, type : 'member', name : 'players_', class : 'Player' },
|
||||
{ line : 90, type : 'member', name : 'field_', class : 'Field' }
|
||||
]}
|
||||
}
|
||||
]});
|
||||
@@ -0,0 +1,551 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Shift Prototype</title>
|
||||
|
||||
<meta name="robots" content="noindex" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="lib/syntaxhighlighter/styles/shCoreDefault.css"/>
|
||||
<link type="text/css" rel="stylesheet" href="style.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="header"></div>
|
||||
<div id="wrapper">
|
||||
<div id="files">
|
||||
<div id="main">
|
||||
<pre class="brush:cpp">
|
||||
#include "tictactoe.h"
|
||||
|
||||
int main() {
|
||||
TicTacToe tictactoe;
|
||||
|
||||
while ( tictactoe.Start() ) {
|
||||
tictactoe.Run();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
<div id="tictactoe">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _TIC_TAC_TOE_
|
||||
#define _TIC_TAC_TOE_
|
||||
|
||||
#include "computer.h"
|
||||
#include "field.h"
|
||||
#include "human.h"
|
||||
#include "input.h"
|
||||
#include "player.h"
|
||||
|
||||
class TicTacToe {
|
||||
public:
|
||||
TicTacToe() {
|
||||
players_[0] = NULL;
|
||||
players_[1] = NULL;
|
||||
}
|
||||
|
||||
~TicTacToe() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool Start() {
|
||||
Reset();
|
||||
std::cout << "Tic Tac Toe\n\n[1] Human\n[2] Computer\n[3] Quit\n\n";
|
||||
|
||||
players_[0] = SelectPlayer( Field::PlayerA, "PlayerA" );
|
||||
if ( !players_[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
players_[1] = SelectPlayer( Field::PlayerB, "PlayerB" );
|
||||
if ( !players_[1] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << '\n';
|
||||
return true;
|
||||
}
|
||||
|
||||
void Run() {
|
||||
field_.Show();
|
||||
|
||||
int playerIndex = 0;
|
||||
|
||||
for ( int i = 0; i < 9; i++ ) {
|
||||
Player& player = *players_[playerIndex];
|
||||
|
||||
field_.MakeMove( player.Turn( field_ ), player.token_ );
|
||||
field_.Show();
|
||||
|
||||
if ( field_.SameInRow( player.token_, 3 ) ) {
|
||||
std::cout << player.name_ << " won!\n\n";
|
||||
return;
|
||||
}
|
||||
|
||||
playerIndex = ( playerIndex + 1 ) % 2;
|
||||
}
|
||||
|
||||
std::cout << "Game ends in draw!\n\n";
|
||||
}
|
||||
|
||||
private:
|
||||
void Reset() {
|
||||
field_.Clear();
|
||||
|
||||
for ( int i = 0; i < 2; i++ ) {
|
||||
if ( players_[i] ) {
|
||||
delete players_[i];
|
||||
players_[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player* SelectPlayer( Field::Token token, const std::string& name ) const {
|
||||
int selection;
|
||||
|
||||
while ( true ) {
|
||||
std::cout << "Choose " << name << ": ";
|
||||
input::number( &selection );
|
||||
|
||||
switch ( selection ) {
|
||||
case 1 : return new HumanPlayer( token, name );
|
||||
case 2 : return new ArtificialPlayer( token, name );
|
||||
case 3 : return NULL;
|
||||
default : std::cout << "Wrong input!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player* players_[2];
|
||||
Field field_;
|
||||
};
|
||||
|
||||
#endif // _TIC_TAC_TOE_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="field">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _FIELD_
|
||||
#define _FIELD_
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
class Field {
|
||||
public:
|
||||
enum Token {
|
||||
None = 0,
|
||||
PlayerA = 1,
|
||||
PlayerB = 4
|
||||
};
|
||||
|
||||
static Token Opponent( Token token ) {
|
||||
assert( token != None );
|
||||
if ( token == PlayerA ) {
|
||||
return PlayerB;
|
||||
} else {
|
||||
return PlayerA;
|
||||
}
|
||||
}
|
||||
|
||||
struct Move {
|
||||
int row;
|
||||
int col;
|
||||
};
|
||||
|
||||
Field()
|
||||
: left_( 9 ) {
|
||||
grid_ = new Token* [3];
|
||||
for ( int i = 0; i < 3 ; i++ ) {
|
||||
grid_[i] = new Token[3];
|
||||
}
|
||||
}
|
||||
|
||||
~Field() {
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
delete grid_[i];
|
||||
}
|
||||
delete [] grid_;
|
||||
}
|
||||
|
||||
Field Clone() const {
|
||||
Field field;
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
for ( int j = 0; j < 3; j++ ) {
|
||||
field.grid_[i][j] = grid_[i][j];
|
||||
}
|
||||
}
|
||||
field.left_ = left_;
|
||||
return field;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
for ( int j = 0; j < 3; j++ ) {
|
||||
grid_[i][j] = None;
|
||||
}
|
||||
}
|
||||
left_ = 9;
|
||||
}
|
||||
|
||||
void Show() const {
|
||||
std::cout << " 1 2 3\n";
|
||||
for ( int row = 0; row < 3; row++ ) {
|
||||
std::cout << row + 1 << " ";
|
||||
|
||||
for ( int col = 0; col < 3; col++ ) {
|
||||
if ( grid_[row][col] == PlayerA ) {
|
||||
std::cout << " X ";
|
||||
} else if ( grid_[row][col] == PlayerB ) {
|
||||
std::cout << " O ";
|
||||
} else {
|
||||
std::cout << " ";
|
||||
}
|
||||
|
||||
if ( col < 2 ) {
|
||||
std::cout << "|";
|
||||
}
|
||||
}
|
||||
|
||||
if ( row < 2 ) {
|
||||
std::cout << "\n -----------\n";
|
||||
}
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
|
||||
int SameInRow( Token token, int amount ) const {
|
||||
int sum = amount * token;
|
||||
int count = 0;
|
||||
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
if ( grid_[i][0] + grid_[i][1] + grid_[i][2] == sum ) {
|
||||
count++;
|
||||
} else if ( grid_[0][i] + grid_[1][i] + grid_[2][i] == sum ) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( grid_[0][0] + grid_[1][1] + grid_[2][2] == sum ) {
|
||||
count++;
|
||||
} else if ( grid_[2][0] + grid_[1][1] + grid_[0][2] == sum ) {
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool InRange( const Move& move ) const {
|
||||
return move.row >= 0 && move.row < 3 && move.col >= 0 && move.col < 3;
|
||||
}
|
||||
|
||||
bool IsEmpty( const Move& move ) const {
|
||||
return grid_[move.row][move.col] == None;
|
||||
}
|
||||
|
||||
bool IsFull() const {
|
||||
return left_ == 0;
|
||||
}
|
||||
|
||||
void MakeMove( const Move& move, Token token ) {
|
||||
assert( InRange( move ) );
|
||||
assert( IsEmpty( move ) );
|
||||
assert( token != None );
|
||||
assert( left_ );
|
||||
|
||||
grid_[move.row][move.col] = token;
|
||||
left_--;
|
||||
}
|
||||
|
||||
void ClearMove( const Move& move ) {
|
||||
assert( InRange(move) );
|
||||
assert( !IsEmpty(move) );
|
||||
assert( left_ < 9 );
|
||||
|
||||
grid_[move.row][move.col] = None;
|
||||
left_++;
|
||||
}
|
||||
|
||||
private:
|
||||
Token** grid_;
|
||||
int left_;
|
||||
};
|
||||
|
||||
#endif // _FIELD_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="player">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _PLAYER_
|
||||
#define _PLAYER_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "field.h"
|
||||
|
||||
class Player {
|
||||
public:
|
||||
Player( Field::Token token, const std::string& name )
|
||||
: token_( token )
|
||||
, name_( name ) {
|
||||
}
|
||||
|
||||
virtual Field::Move Turn( const Field& field ) const = 0;
|
||||
|
||||
const Field::Token token_;
|
||||
const std::string name_;
|
||||
};
|
||||
|
||||
#endif // _PLAYER_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="human">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _HUMAN_
|
||||
#define _HUMAN_
|
||||
|
||||
#include "input.h"
|
||||
#include "player.h"
|
||||
|
||||
class HumanPlayer : public Player {
|
||||
public:
|
||||
HumanPlayer( Field::Token token, const std::string& name )
|
||||
: Player( token, name ) {
|
||||
}
|
||||
|
||||
virtual Field::Move Turn( const Field& field ) const {
|
||||
Field::Move move;
|
||||
std::cout << name_ << '\n';
|
||||
do {
|
||||
move = Input();
|
||||
move.row -= 1;
|
||||
move.col -= 1;
|
||||
} while ( !Check( field, move ) );
|
||||
return move;
|
||||
}
|
||||
|
||||
private:
|
||||
Field::Move Input() const {
|
||||
Field::Move move;
|
||||
|
||||
std::cout << "Insert row: ";
|
||||
input::number( &move.row );
|
||||
|
||||
std::cout << "Insert column: ";
|
||||
input::number( &move.col );
|
||||
|
||||
std::cout << '\n';
|
||||
return move;
|
||||
}
|
||||
|
||||
bool Check( const Field& field, const Field::Move& move ) const {
|
||||
if ( !field.InRange( move ) ) {
|
||||
std::cout << "Wrong input!\n";
|
||||
return false;
|
||||
} else if ( !field.IsEmpty( move ) ) {
|
||||
std::cout << "Is occupied!\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _HUMAN_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="computer">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _ARTIFICIAL_
|
||||
#define _ARTIFICIAL_
|
||||
|
||||
#include "player.h"
|
||||
|
||||
class ArtificialPlayer : public Player {
|
||||
public:
|
||||
ArtificialPlayer( Field::Token token, const std::string& name )
|
||||
: Player( token, name ) {
|
||||
}
|
||||
|
||||
virtual Field::Move Turn( const Field& field ) const {
|
||||
srand( static_cast<unsigned int>( time( NULL ) ) );
|
||||
Field fakeField = field.Clone();
|
||||
Node node = MinMax( fakeField, token_ );
|
||||
return node.move;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Node {
|
||||
Field::Move move;
|
||||
int value;
|
||||
};
|
||||
|
||||
Node MinMax( Field& field, Field::Token token ) const {
|
||||
Node node;
|
||||
node.value = -10000;
|
||||
|
||||
Field::Move move;
|
||||
int sameMove;
|
||||
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
move.row = i;
|
||||
|
||||
for ( int j = 0; j < 3; j++ ) {
|
||||
move.col = j;
|
||||
|
||||
if ( !field.IsEmpty( move ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
field.MakeMove( move, token );
|
||||
|
||||
int turnValue = Evaluate( field, token );
|
||||
if ( !turnValue && !field.IsFull() ) {
|
||||
turnValue = -MinMax( field, Field::Opponent( token ) ).value;
|
||||
}
|
||||
|
||||
field.ClearMove( move );
|
||||
|
||||
if ( turnValue > node.value ) {
|
||||
node.move = move;
|
||||
node.value = turnValue;
|
||||
sameMove = 1;
|
||||
} else if ( turnValue == node.value ) {
|
||||
sameMove++;
|
||||
if ( rand() % sameMove == 0 ) {
|
||||
node.move = move;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
int Evaluate( const Field& field, Field::Token token ) const {
|
||||
if ( field.SameInRow( token, 3 ) ) {
|
||||
return 2;
|
||||
} else if ( field.SameInRow( Field::Opponent( token ), 2 ) ) {
|
||||
return -1;
|
||||
} else if ( field.SameInRow( token, 2 ) > 1 ) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _ARTIFICIAL_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="input">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _INPUT_
|
||||
#define _INPUT_
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace input {
|
||||
|
||||
template<typename T>
|
||||
bool number( T* number ) {
|
||||
std::string input;
|
||||
getline( std::cin, input );
|
||||
std::stringstream stream( input );
|
||||
return stream >> *number;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // _INPUT_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="sample">
|
||||
<pre class="brush:cpp">
|
||||
class Player {
|
||||
public:
|
||||
void Do() {}
|
||||
};
|
||||
|
||||
class Base {};
|
||||
|
||||
class Game : public Base {
|
||||
public:
|
||||
Game() {
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init() {}
|
||||
|
||||
void Run() {
|
||||
player.Do();
|
||||
}
|
||||
|
||||
Player player;
|
||||
};
|
||||
|
||||
Game* game;
|
||||
|
||||
int main() {
|
||||
game = new Game();
|
||||
|
||||
game->Run();
|
||||
|
||||
delete game;
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="paper"></div>
|
||||
</div>
|
||||
|
||||
<script src="lib/jquery-2.0.0.min.js"></script>
|
||||
<script src="lib/jquery.scrollTo-1.4.3.1-min.js"></script>
|
||||
<script src="lib/raphael.js"></script>
|
||||
|
||||
<script src="lib/syntaxhighlighter/scripts/shCore.js"></script>
|
||||
<script src="lib/syntaxhighlighter/scripts/shBrushCpp.js"></script>
|
||||
|
||||
<script src="src/utils/vector.js"></script>
|
||||
<script src="src/utils/utilities.js"></script>
|
||||
<script src="src/utils/raphael_extensions.js"></script>
|
||||
|
||||
<script src="src/shift.js"></script>
|
||||
|
||||
<script src="src/position.js"></script>
|
||||
<script src="src/connection.js"></script>
|
||||
<script src="src/container.js"></script>
|
||||
<script src="src/object.js"></script>
|
||||
|
||||
<script src="src/variable.js"></script>
|
||||
<script src="src/member.js"></script>
|
||||
<script src="src/class.js"></script>
|
||||
<script src="src/function.js"></script>
|
||||
<script src="src/method.js"></script>
|
||||
|
||||
<script src="src/call.js"></script>
|
||||
<script src="src/use.js"></script>
|
||||
<script src="src/association.js"></script>
|
||||
<script src="src/inheritance.js"></script>
|
||||
<script src="src/instantiation.js"></script>
|
||||
|
||||
<script src="src/program.js"></script>
|
||||
<script src="src/interpreter.js"></script>
|
||||
<script src="src/fileviewer.js"></script>
|
||||
|
||||
<script> var data = []; </script>
|
||||
<script src="data/main.js"></script>
|
||||
<script src="data/tictactoe.js"></script>
|
||||
<script src="data/field.js"></script>
|
||||
<script src="data/player.js"></script>
|
||||
<script src="data/human.js"></script>
|
||||
<script src="data/computer.js"></script>
|
||||
<script src="data/input.js"></script>
|
||||
|
||||
<script src="src/main.js"></script>
|
||||
<script> main(); </script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
Copyright (c) 2013, Michael Bostock
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
* The name Michael Bostock may not be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
|
||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
||||
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) 2007-2012 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
|
||||
* Dual licensed under MIT and GPL.
|
||||
* @author Ariel Flesler
|
||||
* @version 1.4.3.1
|
||||
*/
|
||||
;(function($){var h=$.scrollTo=function(a,b,c){$(window).scrollTo(a,b,c)};h.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1,limit:true};h.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(e,f,g){if(typeof f=='object'){g=f;f=0}if(typeof g=='function')g={onAfter:g};if(e=='max')e=9e9;g=$.extend({},h.defaults,g);f=f||g.duration;g.queue=g.queue&&g.axis.length>1;if(g.queue)f/=2;g.offset=both(g.offset);g.over=both(g.over);return this._scrollable().each(function(){if(e==null)return;var d=this,$elem=$(d),targ=e,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}$.each(g.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=h.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(g.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=g.offset[pos]||0;if(g.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*g.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(g.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&g.queue){if(old!=attr[key])animate(g.onAfterFirst);delete attr[key]}});animate(g.onAfter);function animate(a){$elem.animate(attr,f,g.easing,a&&function(){a.call(this,e,g)})}}).end()};h.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);
|
||||
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2003, 2004 Jim Weirich
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* SyntaxHighlighter
|
||||
* http://alexgorbatchev.com/SyntaxHighlighter
|
||||
*
|
||||
* SyntaxHighlighter is donationware. If you are using it, please donate.
|
||||
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
|
||||
*
|
||||
* @version
|
||||
* 3.0.83 (July 02 2010)
|
||||
*
|
||||
* @copyright
|
||||
* Copyright (C) 2004-2010 Alex Gorbatchev.
|
||||
*
|
||||
* @license
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
*/
|
||||
;(function()
|
||||
{
|
||||
// CommonJS
|
||||
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
|
||||
|
||||
function Brush()
|
||||
{
|
||||
// Copyright 2006 Shin, YoungJin
|
||||
|
||||
var datatypes = 'ATOM BOOL BOOLEAN BYTE CHAR COLORREF DWORD DWORDLONG DWORD_PTR ' +
|
||||
'DWORD32 DWORD64 FLOAT HACCEL HALF_PTR HANDLE HBITMAP HBRUSH ' +
|
||||
'HCOLORSPACE HCONV HCONVLIST HCURSOR HDC HDDEDATA HDESK HDROP HDWP ' +
|
||||
'HENHMETAFILE HFILE HFONT HGDIOBJ HGLOBAL HHOOK HICON HINSTANCE HKEY ' +
|
||||
'HKL HLOCAL HMENU HMETAFILE HMODULE HMONITOR HPALETTE HPEN HRESULT ' +
|
||||
'HRGN HRSRC HSZ HWINSTA HWND INT INT_PTR INT32 INT64 LANGID LCID LCTYPE ' +
|
||||
'LGRPID LONG LONGLONG LONG_PTR LONG32 LONG64 LPARAM LPBOOL LPBYTE LPCOLORREF ' +
|
||||
'LPCSTR LPCTSTR LPCVOID LPCWSTR LPDWORD LPHANDLE LPINT LPLONG LPSTR LPTSTR ' +
|
||||
'LPVOID LPWORD LPWSTR LRESULT PBOOL PBOOLEAN PBYTE PCHAR PCSTR PCTSTR PCWSTR ' +
|
||||
'PDWORDLONG PDWORD_PTR PDWORD32 PDWORD64 PFLOAT PHALF_PTR PHANDLE PHKEY PINT ' +
|
||||
'PINT_PTR PINT32 PINT64 PLCID PLONG PLONGLONG PLONG_PTR PLONG32 PLONG64 POINTER_32 ' +
|
||||
'POINTER_64 PSHORT PSIZE_T PSSIZE_T PSTR PTBYTE PTCHAR PTSTR PUCHAR PUHALF_PTR ' +
|
||||
'PUINT PUINT_PTR PUINT32 PUINT64 PULONG PULONGLONG PULONG_PTR PULONG32 PULONG64 ' +
|
||||
'PUSHORT PVOID PWCHAR PWORD PWSTR SC_HANDLE SC_LOCK SERVICE_STATUS_HANDLE SHORT ' +
|
||||
'SIZE_T SSIZE_T TBYTE TCHAR UCHAR UHALF_PTR UINT UINT_PTR UINT32 UINT64 ULONG ' +
|
||||
'ULONGLONG ULONG_PTR ULONG32 ULONG64 USHORT USN VOID WCHAR WORD WPARAM WPARAM WPARAM ' +
|
||||
'char bool short int __int32 __int64 __int8 __int16 long float double __wchar_t ' +
|
||||
'clock_t _complex _dev_t _diskfree_t div_t ldiv_t _exception _EXCEPTION_POINTERS ' +
|
||||
'FILE _finddata_t _finddatai64_t _wfinddata_t _wfinddatai64_t __finddata64_t ' +
|
||||
'__wfinddata64_t _FPIEEE_RECORD fpos_t _HEAPINFO _HFILE lconv intptr_t ' +
|
||||
'jmp_buf mbstate_t _off_t _onexit_t _PNH ptrdiff_t _purecall_handler ' +
|
||||
'sig_atomic_t size_t _stat __stat64 _stati64 terminate_function ' +
|
||||
'time_t __time64_t _timeb __timeb64 tm uintptr_t _utimbuf ' +
|
||||
'va_list wchar_t wctrans_t wctype_t wint_t signed';
|
||||
|
||||
var keywords = 'break case catch class const __finally __exception __try ' +
|
||||
'const_cast continue private public protected __declspec ' +
|
||||
'default delete deprecated dllexport dllimport do dynamic_cast ' +
|
||||
'else enum explicit extern if for friend goto inline ' +
|
||||
'mutable naked namespace new noinline noreturn nothrow ' +
|
||||
'register reinterpret_cast return selectany ' +
|
||||
'sizeof static static_cast struct switch template this ' +
|
||||
'thread throw true false try typedef typeid typename union ' +
|
||||
'using uuid virtual void volatile whcar_t while';
|
||||
|
||||
var functions = 'assert isalnum isalpha iscntrl isdigit isgraph islower isprint' +
|
||||
'ispunct isspace isupper isxdigit tolower toupper errno localeconv ' +
|
||||
'setlocale acos asin atan atan2 ceil cos cosh exp fabs floor fmod ' +
|
||||
'frexp ldexp log log10 modf pow sin sinh sqrt tan tanh jmp_buf ' +
|
||||
'longjmp setjmp raise signal sig_atomic_t va_arg va_end va_start ' +
|
||||
'clearerr fclose feof ferror fflush fgetc fgetpos fgets fopen ' +
|
||||
'fprintf fputc fputs fread freopen fscanf fseek fsetpos ftell ' +
|
||||
'fwrite getc getchar gets perror printf putc putchar puts remove ' +
|
||||
'rename rewind scanf setbuf setvbuf sprintf sscanf tmpfile tmpnam ' +
|
||||
'ungetc vfprintf vprintf vsprintf abort abs atexit atof atoi atol ' +
|
||||
'bsearch calloc div exit free getenv labs ldiv malloc mblen mbstowcs ' +
|
||||
'mbtowc qsort rand realloc srand strtod strtol strtoul system ' +
|
||||
'wcstombs wctomb memchr memcmp memcpy memmove memset strcat strchr ' +
|
||||
'strcmp strcoll strcpy strcspn strerror strlen strncat strncmp ' +
|
||||
'strncpy strpbrk strrchr strspn strstr strtok strxfrm asctime ' +
|
||||
'clock ctime difftime gmtime localtime mktime strftime time';
|
||||
|
||||
this.regexList = [
|
||||
{ regex: SyntaxHighlighter.regexLib.singleLineCComments, css: 'comments' }, // one line comments
|
||||
{ regex: SyntaxHighlighter.regexLib.multiLineCComments, css: 'comments' }, // multiline comments
|
||||
{ regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'string' }, // strings
|
||||
{ regex: SyntaxHighlighter.regexLib.singleQuotedString, css: 'string' }, // strings
|
||||
{ regex: /^ *#.*/gm, css: 'preprocessor' },
|
||||
{ regex: new RegExp(this.getKeywords(datatypes), 'gm'), css: 'color1 bold' },
|
||||
{ regex: new RegExp(this.getKeywords(functions), 'gm'), css: 'functions bold' },
|
||||
{ regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword bold' }
|
||||
];
|
||||
};
|
||||
|
||||
Brush.prototype = new SyntaxHighlighter.Highlighter();
|
||||
Brush.aliases = ['cpp', 'c'];
|
||||
|
||||
SyntaxHighlighter.brushes.Cpp = Brush;
|
||||
|
||||
// CommonJS
|
||||
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
|
||||
})();
|
||||
@@ -0,0 +1,328 @@
|
||||
/**
|
||||
* SyntaxHighlighter
|
||||
* http://alexgorbatchev.com/SyntaxHighlighter
|
||||
*
|
||||
* SyntaxHighlighter is donationware. If you are using it, please donate.
|
||||
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
|
||||
*
|
||||
* @version
|
||||
* 3.0.83 (July 02 2010)
|
||||
*
|
||||
* @copyright
|
||||
* Copyright (C) 2004-2010 Alex Gorbatchev.
|
||||
*
|
||||
* @license
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
*/
|
||||
.syntaxhighlighter a,
|
||||
.syntaxhighlighter div,
|
||||
.syntaxhighlighter code,
|
||||
.syntaxhighlighter table,
|
||||
.syntaxhighlighter table td,
|
||||
.syntaxhighlighter table tr,
|
||||
.syntaxhighlighter table tbody,
|
||||
.syntaxhighlighter table thead,
|
||||
.syntaxhighlighter table caption,
|
||||
.syntaxhighlighter textarea {
|
||||
-moz-border-radius: 0 0 0 0 !important;
|
||||
-webkit-border-radius: 0 0 0 0 !important;
|
||||
background: none !important;
|
||||
border: 0 !important;
|
||||
bottom: auto !important;
|
||||
float: none !important;
|
||||
height: auto !important;
|
||||
left: auto !important;
|
||||
line-height: 1.1em !important;
|
||||
margin: 0 !important;
|
||||
outline: 0 !important;
|
||||
overflow: visible !important;
|
||||
padding: 0 !important;
|
||||
position: static !important;
|
||||
right: auto !important;
|
||||
text-align: left !important;
|
||||
top: auto !important;
|
||||
vertical-align: baseline !important;
|
||||
width: auto !important;
|
||||
box-sizing: content-box !important;
|
||||
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
|
||||
font-weight: normal !important;
|
||||
font-style: normal !important;
|
||||
font-size: 10pt !important;
|
||||
min-height: inherit !important;
|
||||
min-height: auto !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter {
|
||||
width: 100% !important;
|
||||
margin: 1em 0 1em 0 !important;
|
||||
position: relative !important;
|
||||
overflow: auto !important;
|
||||
font-size: 1em !important;
|
||||
}
|
||||
.syntaxhighlighter.source {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
.syntaxhighlighter .bold {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
.syntaxhighlighter .italic {
|
||||
font-style: italic !important;
|
||||
}
|
||||
.syntaxhighlighter .line {
|
||||
white-space: pre !important;
|
||||
}
|
||||
.syntaxhighlighter table {
|
||||
width: 100% !important;
|
||||
}
|
||||
.syntaxhighlighter table caption {
|
||||
text-align: left !important;
|
||||
padding: .5em 0 0.5em 1em !important;
|
||||
}
|
||||
.syntaxhighlighter table td.code {
|
||||
width: 100% !important;
|
||||
}
|
||||
.syntaxhighlighter table td.code .container {
|
||||
position: relative !important;
|
||||
}
|
||||
.syntaxhighlighter table td.code .container textarea {
|
||||
box-sizing: border-box !important;
|
||||
position: absolute !important;
|
||||
left: 0 !important;
|
||||
top: 0 !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
border: none !important;
|
||||
background: white !important;
|
||||
padding-left: 1em !important;
|
||||
overflow: hidden !important;
|
||||
white-space: pre !important;
|
||||
}
|
||||
.syntaxhighlighter table td.gutter .line {
|
||||
text-align: right !important;
|
||||
padding: 0 0.5em 0 1em !important;
|
||||
}
|
||||
.syntaxhighlighter table td.code .line {
|
||||
padding: 0 1em !important;
|
||||
}
|
||||
.syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
|
||||
padding-left: 0em !important;
|
||||
}
|
||||
.syntaxhighlighter.show {
|
||||
display: block !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed table {
|
||||
display: none !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar {
|
||||
padding: 0.1em 0.8em 0em 0.8em !important;
|
||||
font-size: 1em !important;
|
||||
position: static !important;
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar span {
|
||||
display: inline !important;
|
||||
margin-right: 1em !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar span a {
|
||||
padding: 0 !important;
|
||||
display: none !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar span a.expandSource {
|
||||
display: inline !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar {
|
||||
position: absolute !important;
|
||||
right: 1px !important;
|
||||
top: 1px !important;
|
||||
width: 11px !important;
|
||||
height: 11px !important;
|
||||
font-size: 10px !important;
|
||||
z-index: 10 !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar span.title {
|
||||
display: inline !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar a {
|
||||
display: block !important;
|
||||
text-align: center !important;
|
||||
text-decoration: none !important;
|
||||
padding-top: 1px !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar a.expandSource {
|
||||
display: none !important;
|
||||
}
|
||||
.syntaxhighlighter.ie {
|
||||
font-size: .9em !important;
|
||||
padding: 1px 0 1px 0 !important;
|
||||
}
|
||||
.syntaxhighlighter.ie .toolbar {
|
||||
line-height: 8px !important;
|
||||
}
|
||||
.syntaxhighlighter.ie .toolbar a {
|
||||
padding-top: 0px !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .line.alt1 .content,
|
||||
.syntaxhighlighter.printing .line.alt2 .content,
|
||||
.syntaxhighlighter.printing .line.highlighted .number,
|
||||
.syntaxhighlighter.printing .line.highlighted.alt1 .content,
|
||||
.syntaxhighlighter.printing .line.highlighted.alt2 .content {
|
||||
background: none !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .line .number {
|
||||
color: #bbbbbb !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .line .content {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .toolbar {
|
||||
display: none !important;
|
||||
}
|
||||
.syntaxhighlighter.printing a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
|
||||
color: #008200 !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
|
||||
color: blue !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .keyword {
|
||||
color: #006699 !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .preprocessor {
|
||||
color: gray !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .variable {
|
||||
color: #aa7700 !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .value {
|
||||
color: #009900 !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .functions {
|
||||
color: #ff1493 !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .constants {
|
||||
color: #0066cc !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .script {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
|
||||
color: gray !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
|
||||
color: #ff1493 !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
|
||||
color: red !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter {
|
||||
background-color: white !important;
|
||||
}
|
||||
.syntaxhighlighter .line.alt1 {
|
||||
background-color: white !important;
|
||||
}
|
||||
.syntaxhighlighter .line.alt2 {
|
||||
background-color: white !important;
|
||||
}
|
||||
.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
|
||||
background-color: #e0e0e0 !important;
|
||||
}
|
||||
.syntaxhighlighter .line.highlighted.number {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter table caption {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter .gutter {
|
||||
color: #afafaf !important;
|
||||
}
|
||||
.syntaxhighlighter .gutter .line {
|
||||
border-right: 3px solid #6ce26c !important;
|
||||
}
|
||||
.syntaxhighlighter .gutter .line.highlighted {
|
||||
background-color: #6ce26c !important;
|
||||
color: white !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .line .content {
|
||||
border: none !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed {
|
||||
overflow: visible !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar {
|
||||
color: blue !important;
|
||||
background: white !important;
|
||||
border: 1px solid #6ce26c !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar a {
|
||||
color: blue !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar a:hover {
|
||||
color: red !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar {
|
||||
color: white !important;
|
||||
background: #6ce26c !important;
|
||||
border: none !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar a {
|
||||
color: white !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar a:hover {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter .plain, .syntaxhighlighter .plain a {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter .comments, .syntaxhighlighter .comments a {
|
||||
color: #008200 !important;
|
||||
}
|
||||
.syntaxhighlighter .string, .syntaxhighlighter .string a {
|
||||
color: blue !important;
|
||||
}
|
||||
.syntaxhighlighter .keyword {
|
||||
color: #006699 !important;
|
||||
}
|
||||
.syntaxhighlighter .preprocessor {
|
||||
color: gray !important;
|
||||
}
|
||||
.syntaxhighlighter .variable {
|
||||
color: #aa7700 !important;
|
||||
}
|
||||
.syntaxhighlighter .value {
|
||||
color: #009900 !important;
|
||||
}
|
||||
.syntaxhighlighter .functions {
|
||||
color: #ff1493 !important;
|
||||
}
|
||||
.syntaxhighlighter .constants {
|
||||
color: #0066cc !important;
|
||||
}
|
||||
.syntaxhighlighter .script {
|
||||
font-weight: bold !important;
|
||||
color: #006699 !important;
|
||||
background-color: none !important;
|
||||
}
|
||||
.syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
|
||||
color: gray !important;
|
||||
}
|
||||
.syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
|
||||
color: #ff1493 !important;
|
||||
}
|
||||
.syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter .keyword {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
SHIFT.Association = function( name, from, to ) {
|
||||
SHIFT.Connection.call( this, name, from, to );
|
||||
|
||||
this.count = 0;
|
||||
}
|
||||
|
||||
SHIFT.Association.prototype = {
|
||||
__proto__ : SHIFT.Connection.prototype,
|
||||
|
||||
type : SHIFT.Types.Association,
|
||||
|
||||
color : 'lightblue',
|
||||
highlight : '#3EC3EE',
|
||||
|
||||
CreateNode : function( paper, fromNode, toNode, sameClass ) {
|
||||
var fromClass = this.from.type === SHIFT.Types.Class;
|
||||
var toClass = this.to.type === SHIFT.Types.Class;
|
||||
var node;
|
||||
|
||||
if ( sameClass ) {
|
||||
node = paper.bow( fromNode, toNode, 0.3 );
|
||||
} else if ( fromClass && toClass ) {
|
||||
node = paper.shortest( fromNode, toNode );
|
||||
} else if ( fromClass ) {
|
||||
node = paper.shortest2( fromNode, toNode );
|
||||
} else if ( toClass ) {
|
||||
node = paper.shortest2( toNode, fromNode );
|
||||
} else {
|
||||
node = paper.connection( fromNode, toNode );
|
||||
}
|
||||
return node.line( this.color, 1 + this.count * 0.5 );
|
||||
},
|
||||
|
||||
Increment : function() {
|
||||
this.count++;
|
||||
},
|
||||
|
||||
Decrement : function() {
|
||||
this.count--;
|
||||
if ( this.count === 0 ) {
|
||||
this.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
SHIFT.Call = function( name, caller, callee ) {
|
||||
SHIFT.Connection.call( this, name, caller, callee );
|
||||
|
||||
this.abstraction = SHIFT.Abstraction.None;
|
||||
}
|
||||
|
||||
SHIFT.Call.prototype = {
|
||||
__proto__ : SHIFT.Connection.prototype,
|
||||
|
||||
type : SHIFT.Types.Call,
|
||||
|
||||
CreateNode : function( paper, fromNode, toNode, sameClass ) {
|
||||
var set = paper.set();
|
||||
var line;
|
||||
if ( sameClass ) {
|
||||
line = paper.bow( fromNode, toNode, 3 );
|
||||
} else {
|
||||
line = paper.wave( fromNode, toNode );
|
||||
}
|
||||
|
||||
line.line( this.color );
|
||||
|
||||
if ( this.abstraction === SHIFT.Abstraction.Virtual ) {
|
||||
line.dash();
|
||||
}
|
||||
|
||||
var end = line.points[1];
|
||||
var arrow = paper.arrow( end.x, end.y, end.i ).line( this.color );
|
||||
return set.push( line, arrow );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,256 @@
|
||||
SHIFT.Class = function( name ) {
|
||||
SHIFT.Object.call( this, name );
|
||||
SHIFT.Container.call( this );
|
||||
|
||||
this.base = null;
|
||||
|
||||
this.publicOpen = false;
|
||||
this.privateOpen = false;
|
||||
|
||||
this.publics = [];
|
||||
this.privates = [];
|
||||
|
||||
this.visibility = SHIFT.Visibility.Public;
|
||||
this.abstraction = SHIFT.Abstraction.None;
|
||||
|
||||
this.privateObject = new SHIFT.Object( 'Private' );
|
||||
this.privateObject.parent = this;
|
||||
this.privateObject.active = true;
|
||||
this.privateObject.Open = function() {
|
||||
this.parent.Open();
|
||||
}
|
||||
}
|
||||
|
||||
SHIFT.Class.prototype = {
|
||||
__proto__ : extend( new SHIFT.Object, SHIFT.Container.prototype ),
|
||||
|
||||
type : SHIFT.Types.Class,
|
||||
|
||||
GetMember : function( name ) {
|
||||
return this.Get( SHIFT.Member, name );
|
||||
},
|
||||
|
||||
GetMethod : function( name ) {
|
||||
return this.Get( SHIFT.Method, name );
|
||||
},
|
||||
|
||||
CreateMember : function( name, location, visibility, abstraction ) {
|
||||
return this.Create( SHIFT.Member, name, location, visibility, abstraction );
|
||||
},
|
||||
|
||||
CreateMethod : function( name, location, visibility, abstraction ) {
|
||||
return this.Create( SHIFT.Method, name, location, visibility, abstraction );
|
||||
},
|
||||
|
||||
CreateClass : function( name, location, visibility, abstraction ) {
|
||||
var classModel = this.Create( SHIFT.Class, name, location, visibility, abstraction );
|
||||
classModel.dragable = false;
|
||||
return classModel;
|
||||
},
|
||||
|
||||
Create : function( type, name, location, visibility, abstraction ) {
|
||||
var obj = SHIFT.Container.prototype.Create.call( this, type, name, location );
|
||||
if ( visibility ) {
|
||||
obj.visibility = visibility;
|
||||
if ( visibility === SHIFT.Visibility.Public ) {
|
||||
this.publics.push( obj );
|
||||
} else {
|
||||
this.privates.push( obj );
|
||||
}
|
||||
}
|
||||
if ( abstraction ) {
|
||||
obj.abstraction = abstraction;
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
CreateNode : function( paper, x, y ) {
|
||||
var contents = [];
|
||||
var width = 0;
|
||||
var height = 30;
|
||||
var bb;
|
||||
|
||||
var privateTop = 0;
|
||||
var privateSet = null;
|
||||
|
||||
if ( this.objects.length > this.publics.length + this.privates.length ) {
|
||||
this.publics = this.objects;
|
||||
}
|
||||
|
||||
var node, dots;
|
||||
if ( this.publicOpen ) {
|
||||
if ( this.publics.length ) {
|
||||
if ( this.privates.length ) {
|
||||
var publicText = paper.text( x, y + height + 10, 'public' ).code( 14 );
|
||||
contents.push( publicText );
|
||||
width = Math.max( publicText.getBBox().width, width );
|
||||
height += 20;
|
||||
}
|
||||
|
||||
for ( var i = 0; i < this.publics.length; i++ ) {
|
||||
node = this.publics[i].Show( paper, x, y + height );
|
||||
if ( node ) {
|
||||
contents.push( node );
|
||||
bb = node.getBBox();
|
||||
height += bb.height + 5;
|
||||
width = Math.max( bb.width, width );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( this.privates.length ) {
|
||||
for ( var i = 0; i < this.privates.length; i++ ) {
|
||||
this.privates[i].parent = this.privateObject;
|
||||
}
|
||||
|
||||
var privateText = paper.text( x, y + height + 12, 'private' ).code( 14 );
|
||||
privateText.click( this.ClickPrivate, this );
|
||||
contents.push( privateText );
|
||||
width = Math.max( privateText.getBBox().width, width );
|
||||
privateTop = height;
|
||||
height += 20;
|
||||
|
||||
if ( this.privateOpen ) {
|
||||
for ( var i = 0; i < this.privates.length; i++ ) {
|
||||
node = this.privates[i].Show( paper, x, y + height );
|
||||
if ( node ) {
|
||||
contents.push( node );
|
||||
bb = node.getBBox();
|
||||
height += bb.height + 5;
|
||||
width = Math.max( bb.width, width );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dots = paper.text( x, y + height + 2, "..." ).code( 14 );
|
||||
dots.click( this.ClickPrivate, this );
|
||||
contents.push( dots );
|
||||
height += 10;
|
||||
}
|
||||
}
|
||||
} else if ( this.publics.length ) {
|
||||
var dots = paper.text( x, y + height + 2, "..." ).code( 14 );
|
||||
dots.click( this.ClickPublic, this );
|
||||
contents.push( dots );
|
||||
height += 10;
|
||||
}
|
||||
|
||||
var text = paper.text( x, y + 18, this.name ).code( 18 );
|
||||
width = Math.max( text.getBBox().width, width ) + 20;
|
||||
x -= width / 2;
|
||||
|
||||
if ( privateTop ) {
|
||||
var privateRect = paper.rect( x, y + privateTop, width, height - privateTop, 5 ).box().toBack();
|
||||
privateRect.click( this.ClickPrivate, this );
|
||||
contents.push( privateRect );
|
||||
|
||||
if ( !this.privateOpen ) {
|
||||
this.privateObject.node = paper.set().push( privateRect, privateText, dots );
|
||||
privateRect.hover( this.HoverIn, this.HoverOut, this.privateObject, this.privateObject );
|
||||
privateText.hover( this.HoverIn, this.HoverOut, this.privateObject, this.privateObject );
|
||||
dots.hover( this.HoverIn, this.HoverOut, this.privateObject, this.privateObject );
|
||||
}
|
||||
}
|
||||
|
||||
var rect = paper.rect( x, y, width, height, 5 ).box().toBack();
|
||||
if ( this.abstraction === SHIFT.Abstraction.PureVirtual ) {
|
||||
rect.dash();
|
||||
}
|
||||
|
||||
var set = paper.set();
|
||||
set.push( rect, text );
|
||||
set.push.apply( set, contents );
|
||||
text.click( this.ClickPublic, this );
|
||||
rect.click( this.ClickPublic, this );
|
||||
return set;
|
||||
},
|
||||
|
||||
ClickPublic : function() {
|
||||
if ( this.move.normSquared() || !this.active ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.publicOpen = !this.publicOpen;
|
||||
this.LastParent().Update( this.node.paper );
|
||||
},
|
||||
|
||||
ClickPrivate : function() {
|
||||
if ( this.move.normSquared() || !this.active ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.privateOpen = !this.privateOpen;
|
||||
this.LastParent().Update( this.node.paper );
|
||||
},
|
||||
|
||||
Remove : function() {
|
||||
SHIFT.Object.prototype.Remove.call( this );
|
||||
this.privateObject.Remove();
|
||||
|
||||
for ( var i = 0; i < this.objects.length; i++ ) {
|
||||
this.objects[i].Remove();
|
||||
}
|
||||
},
|
||||
|
||||
Update : function( paper ) {
|
||||
this.Remove();
|
||||
|
||||
this.Show( paper, this.pos.x, this.pos.y );
|
||||
this.UpdateConnections( paper );
|
||||
},
|
||||
|
||||
UpdateConnections : function( paper ) {
|
||||
for ( var i = 0; i < this.objects.length; i++ ) {
|
||||
this.objects[i].UpdateConnections( paper );
|
||||
}
|
||||
|
||||
SHIFT.Connectable.prototype.UpdateConnections.call( this, paper );
|
||||
},
|
||||
|
||||
CheckVirtualCall : function( method ) {
|
||||
if ( this.base ) {
|
||||
var baseMethod = this.FindBy( this.base.objects, 'name', method.name );
|
||||
if ( baseMethod && baseMethod.type === SHIFT.Types.Method &&
|
||||
( baseMethod.abstraction === SHIFT.Abstraction.Virtual ||
|
||||
baseMethod.abstraction === SHIFT.Abstraction.PureVirtual ) ) {
|
||||
var callModel = this.parent.AddCall( baseMethod, method, null );
|
||||
callModel.abstraction = SHIFT.Abstraction.Virtual;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Awake : function() {
|
||||
this.active = true;
|
||||
this.privateObject.active = true;
|
||||
|
||||
for ( var i = 0; i < this.objects.length; i++ ) {
|
||||
this.objects[i].active = true;
|
||||
}
|
||||
|
||||
this.LastParent().Update( this.node.paper );
|
||||
},
|
||||
|
||||
Fade : function() {
|
||||
this.active = false;
|
||||
this.privateObject.active = false;
|
||||
this.publicOpen = false;
|
||||
this.privateOpen = false;
|
||||
|
||||
for ( var i = 0; i < this.objects.length; i++ ) {
|
||||
this.objects[i].active = false;
|
||||
}
|
||||
|
||||
this.LastParent().Update( this.node.paper );
|
||||
},
|
||||
|
||||
Open : function() {
|
||||
if ( !this.publicOpen ) {
|
||||
this.publicOpen = true;
|
||||
this.LastParent().Update( this.node.paper );
|
||||
} else if ( !this.privateOpen ) {
|
||||
this.privateOpen = true;
|
||||
this.LastParent().Update( this.node.paper );
|
||||
} else {
|
||||
console.error( 'class is already open' );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
SHIFT.Connection = function( name, from, to ) {
|
||||
this.name = name;
|
||||
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
|
||||
this.node = null;
|
||||
this.hoverNode = null;
|
||||
|
||||
this.locations = [];
|
||||
this.association = null;
|
||||
|
||||
from.AddConnection( this );
|
||||
to.AddConnection( this );
|
||||
}
|
||||
|
||||
SHIFT.Connection.prototype = {
|
||||
|
||||
color : SHIFT.Colors.light,
|
||||
highlight : '#EC3636',
|
||||
|
||||
Show : function( paper ) {
|
||||
if ( !this.type.visible ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var from = this.from;
|
||||
var to = this.to;
|
||||
|
||||
var fromParent = from.LastParent();
|
||||
var toParent = to.LastParent();
|
||||
|
||||
if ( !from.node || !to.node ) {
|
||||
this.association = this.CreateAssociation( paper, from.NextParentWithNode(), to.NextParentWithNode() );
|
||||
} else {
|
||||
var sameClass = fromParent.type === SHIFT.Types.Class && fromParent === toParent;
|
||||
this.node = this.CreateNode( paper, from.node, to.node, sameClass );
|
||||
}
|
||||
|
||||
if ( this.node ) {
|
||||
this.hoverNode = this.node.clone();
|
||||
this.hoverNode.line( 'rgba(0,0,0,0)', 10 ).hover( this.Hover, this.Hovered, this, this );
|
||||
this.hoverNode.hover( this.Hover, this.Hovered, this, this );
|
||||
this.node.hover( this.Hover, this.Hovered, this, this );
|
||||
|
||||
this.node.click( this.Click, this );
|
||||
this.hoverNode.click( this.Click, this );
|
||||
|
||||
if ( !from.active || !to.active ) {
|
||||
this.node.hide();
|
||||
this.hoverNode.hide();
|
||||
}
|
||||
}
|
||||
|
||||
return this.node;
|
||||
},
|
||||
|
||||
CreateNode : function( paper, fromNode, toNode, sameClass ) {
|
||||
console.error( 'not implemented' );
|
||||
},
|
||||
|
||||
CreateAssociation : function( paper, from, to ) {
|
||||
if ( !from || !to || from === to ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var association = from.GetProgram().AddAssociation( from, to );
|
||||
association.Update( paper );
|
||||
association.Increment();
|
||||
return association;
|
||||
},
|
||||
|
||||
Remove : function() {
|
||||
if ( this.node ) {
|
||||
this.node.remove();
|
||||
}
|
||||
if ( this.hoverNode ) {
|
||||
this.hoverNode.remove();
|
||||
}
|
||||
this.node = null;
|
||||
},
|
||||
|
||||
Update : function( paper ) {
|
||||
this.Remove();
|
||||
|
||||
if ( this.association ) {
|
||||
this.association.Decrement();
|
||||
this.association = null;
|
||||
}
|
||||
|
||||
this.Show( paper );
|
||||
},
|
||||
|
||||
Hover : function( direct ) {
|
||||
if ( this.node ) {
|
||||
if ( !direct ) {
|
||||
this.node.show();
|
||||
}
|
||||
this.node.toFront().stroke( this.highlight );
|
||||
}
|
||||
},
|
||||
|
||||
Hovered : function() {
|
||||
if ( this.node ) {
|
||||
if ( !this.from.active || !this.to.active ) {
|
||||
this.node.hide();
|
||||
}
|
||||
this.node.stroke( this.color );
|
||||
}
|
||||
},
|
||||
|
||||
Click : function() {
|
||||
if ( this.locations.length ) {
|
||||
SHIFT.FileViewer.ShowLocations( this.locations );
|
||||
} else if ( this.type === SHIFT.Types.Association ) {
|
||||
this.from.Open();
|
||||
this.to.Open();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SHIFT.Connectable = function() {
|
||||
this.connections = [];
|
||||
}
|
||||
|
||||
SHIFT.Connectable.prototype = {
|
||||
AddConnection : function( connection ) {
|
||||
if ( connection.from === this ) {
|
||||
this.connections.unshift( connection );
|
||||
} else if ( connection.to === this ) {
|
||||
this.connections.push( connection );
|
||||
} else {
|
||||
console.error( 'This object is not associated with the connection' );
|
||||
}
|
||||
},
|
||||
|
||||
UpdateConnections : function( paper ) {
|
||||
for ( var i = 0; i < this.connections.length; i++ ) {
|
||||
if ( this.connections[i].type !== SHIFT.Types.Association ) {
|
||||
this.connections[i].Update( paper );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
SHIFT.Container = function() {
|
||||
this.objects = [];
|
||||
this.connections = [];
|
||||
}
|
||||
|
||||
SHIFT.Container.prototype = {
|
||||
Get : function( type, name, ignoreBase ) {
|
||||
var obj = this.FindBy( this.objects, 'name', name );
|
||||
|
||||
if ( !ignoreBase && !obj && this.base ) {
|
||||
obj = this.FindBy( this.base.objects, 'name', name );
|
||||
}
|
||||
|
||||
if ( !obj ) {
|
||||
obj = new type( name );
|
||||
this.objects.push( obj );
|
||||
obj.parent = this;
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
Create : function( type, name, location ) {
|
||||
var obj = this.Get( type, name, true );
|
||||
if ( obj.location ) {
|
||||
console.error( 'Location already set!', obj );
|
||||
} else {
|
||||
obj.location = location;
|
||||
obj.active = true;
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
Connect : function( type, from, to, location ) {
|
||||
var name = type.prototype.type.name + ':' + from.Name() + '->' + to.Name();
|
||||
var obj = this.FindBy( this.connections, 'name', name );
|
||||
if ( !obj ) {
|
||||
obj = new type( name, from, to );
|
||||
this.connections.push( obj );
|
||||
}
|
||||
obj.locations.push( location );
|
||||
return obj;
|
||||
},
|
||||
|
||||
FindBy : function( array, key, value ) {
|
||||
for ( var i = 0; i < array.length; i++ ) {
|
||||
if ( array[i][key] === value ) {
|
||||
return array[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
FindAllBy : function( array, key, value ) {
|
||||
var all = [];
|
||||
for ( var i = 0; i < array.length; i++ ) {
|
||||
if ( array[i][key] === value ) {
|
||||
all.push( array[i] );
|
||||
}
|
||||
}
|
||||
return all;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
SHIFT.FileViewer = {
|
||||
|
||||
lastFile : null,
|
||||
lastLines : [],
|
||||
|
||||
Init : function() {
|
||||
SyntaxHighlighter.defaults['tab-size'] = 2;
|
||||
SyntaxHighlighter.defaults['toolbar'] = false;
|
||||
SyntaxHighlighter.all();
|
||||
},
|
||||
|
||||
ShowNavigation : function() {
|
||||
var name;
|
||||
for ( var i = 0; i < data.length; i++ ) {
|
||||
var fileName = data[i].name;
|
||||
name = fileName.split( '.' )[0];
|
||||
$( '<div id="' + name + '_button">' ).text( fileName ).appendTo( '#header' ).click( function( name ) {
|
||||
return function() {
|
||||
SHIFT.FileViewer.ShowFile( name );
|
||||
}
|
||||
}( name ));
|
||||
|
||||
if ( i === 0 ) {
|
||||
this.ShowFile( name );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
ShowFile : function( file ) {
|
||||
if ( this.lastLines.length ) {
|
||||
for ( var i = 0; i < this.lastLines.length; i++ ) {
|
||||
$( '#' + this.lastFile + ' .code .number' + this.lastLines[i] ).removeClass( 'highlighted' );
|
||||
}
|
||||
this.lastLines = [];
|
||||
}
|
||||
|
||||
if ( this.lastFile === file ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.lastFile ) {
|
||||
$( '#' + this.lastFile ).hide();
|
||||
$( '#' + this.lastFile + '_button' ).removeClass( 'selected' );
|
||||
}
|
||||
|
||||
$( '#' + file ).show();
|
||||
$( '#' + file + '_button' ).toggleClass( 'selected' );
|
||||
this.lastFile = file;
|
||||
},
|
||||
|
||||
ShowLocation : function( location ) {
|
||||
this.ShowFile( location.fileName );
|
||||
this.ShowLine( location.lineNumber );
|
||||
this.ScrollToLine( location.lineNumber );
|
||||
},
|
||||
|
||||
ShowLocations : function( locations ) {
|
||||
this.ShowFile( locations[0].fileName );
|
||||
for ( var i = 0; i < locations.length; i++ ) {
|
||||
this.ShowLine( locations[i].lineNumber );
|
||||
}
|
||||
this.ScrollToLine( locations[0].lineNumber );
|
||||
},
|
||||
|
||||
ShowLine : function( line ) {
|
||||
$( '#' + this.lastFile + ' .code .number' + line ).addClass( 'highlighted' );
|
||||
this.lastLines.push( line );
|
||||
},
|
||||
|
||||
ScrollToLine : function( line ) {
|
||||
$( '#files' ).scrollTo( '#' + this.lastFile + ' .code .number' + line, { offset : -200 } );
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,29 @@
|
||||
SHIFT.Function = function( name ) {
|
||||
SHIFT.Object.call( this, name );
|
||||
|
||||
this.return = null;
|
||||
this.params = null;
|
||||
}
|
||||
|
||||
SHIFT.Function.prototype = {
|
||||
__proto__ : SHIFT.Object.prototype,
|
||||
|
||||
type : SHIFT.Types.Function,
|
||||
|
||||
CreateNode : function( paper, x, y ) {
|
||||
y += 12;
|
||||
var t = this.name;
|
||||
// if ( this.return ) {
|
||||
// t = this.return + ' ' + t;
|
||||
// }
|
||||
// if ( this.params ) {
|
||||
// t += '( ' + this.params.join( ', ' ) + ' )';
|
||||
// }
|
||||
|
||||
var text = paper.text( x, y + 2, t ).code( 14 );
|
||||
var bb = text.getBBox();
|
||||
var ellipse = paper.ellipse( x, y, bb.width / 2 + 10, bb.height / 2 + 4 ).box();
|
||||
text.toFront();
|
||||
return paper.set().push( ellipse, text );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
SHIFT.Inheritance = function( name, base, derived ) {
|
||||
SHIFT.Connection.call( this, name, base, derived );
|
||||
|
||||
derived.base = base;
|
||||
}
|
||||
|
||||
SHIFT.Inheritance.prototype = {
|
||||
__proto__ : SHIFT.Connection.prototype,
|
||||
|
||||
type : SHIFT.Types.Inheritance,
|
||||
|
||||
CreateNode : function( paper, fromNode, toNode, sameClass ) {
|
||||
if ( sameClass ) {
|
||||
return paper.bow( fromNode, toNode, 5 ).line( this.color );
|
||||
} else {
|
||||
return paper.arrow2( fromNode, toNode ).line( this.color );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
SHIFT.Instantiation = function( name, variable, classModel ) {
|
||||
SHIFT.Inheritance.call( this, name, classModel, variable );
|
||||
}
|
||||
|
||||
SHIFT.Instantiation.prototype = {
|
||||
__proto__ : SHIFT.Inheritance.prototype,
|
||||
|
||||
type : SHIFT.Types.Instantiation,
|
||||
|
||||
CreateNode : function( paper, fromNode, toNode, sameClass ) {
|
||||
return SHIFT.Inheritance.prototype.CreateNode.call( this, paper, fromNode, toNode, sameClass ).dash();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
SHIFT.Interpreter = {
|
||||
visibility : SHIFT.Visibility.None,
|
||||
abstraction : SHIFT.Abstraction.None,
|
||||
|
||||
CreateProgram : function( data ) {
|
||||
var program = new SHIFT.Program();
|
||||
|
||||
for ( var i = 0; i < data.length; i++ ) {
|
||||
this.ParseNode( data[i], program, program );
|
||||
}
|
||||
return program;
|
||||
},
|
||||
|
||||
ParseNode : function( node, program, namespace ) {
|
||||
if ( !this[node.type] ) {
|
||||
console.error( 'Unknown node type', node.type, node );
|
||||
return;
|
||||
}
|
||||
|
||||
this[node.type]( node, program, namespace );
|
||||
},
|
||||
|
||||
ParseContent : function( content, program, namespace ) {
|
||||
if ( !content ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( var i = 0; i < content.length; i++ ) {
|
||||
this.ParseNode( content[i], program, namespace );
|
||||
}
|
||||
},
|
||||
|
||||
file : function( node, program, namespace ) {
|
||||
this.fileName = node.name.split( '.' )[0];
|
||||
this.ParseContent( node.content, program, namespace );
|
||||
},
|
||||
|
||||
class : function( node, program, namespace ) {
|
||||
var classModel = namespace.CreateClass( node.name, this.CreateLocation( node.line ), this.visibility );
|
||||
|
||||
if ( node.base ) {
|
||||
program.AddInheritance( program.GetClass( node.base ), classModel, this.CreateLocation( node.line ) );
|
||||
}
|
||||
|
||||
if ( node.content ) {
|
||||
var visibility = this.visibility;
|
||||
|
||||
if ( node.content.public ) {
|
||||
this.visibility = SHIFT.Visibility.Public;
|
||||
this.ParseContent( node.content.public, program, classModel );
|
||||
}
|
||||
|
||||
if ( node.content.private ) {
|
||||
this.visibility = SHIFT.Visibility.Private;
|
||||
this.ParseContent( node.content.private, program, classModel );
|
||||
}
|
||||
|
||||
this.visibility = visibility;
|
||||
}
|
||||
},
|
||||
|
||||
member : function( node, program, namespace ) {
|
||||
var member = namespace.CreateMember( node.name, this.CreateLocation( node.line ), this.visibility, this.abstraction );
|
||||
if ( node.class ) {
|
||||
member.typename = node.class;
|
||||
program.AddInstantiation( member, program.GetClass( node.class ), this.CreateLocation( node.line ) );
|
||||
}
|
||||
if ( node.abstraction ) {
|
||||
this.AddAbstraction( member, node.abstraction );
|
||||
}
|
||||
},
|
||||
|
||||
method : function( node, program, namespace ) {
|
||||
var methodModel = namespace.CreateMethod( node.name, this.CreateLocation( node.line ), this.visibility, this.abstraction );
|
||||
this.AddParams( methodModel, node, program );
|
||||
if ( node.abstraction ) {
|
||||
this.AddAbstraction( methodModel, node.abstraction );
|
||||
}
|
||||
this.ParseContent( node.content, program, methodModel );
|
||||
},
|
||||
|
||||
AddAbstraction : function( obj, abstraction ) {
|
||||
switch ( abstraction ) {
|
||||
case 'static' : obj.SetAbstraction( SHIFT.Abstraction.Static ); break;
|
||||
case 'virtual' : obj.SetAbstraction( SHIFT.Abstraction.Virtual ); break;
|
||||
case 'pure_virtual' : obj.SetAbstraction( SHIFT.Abstraction.PureVirtual ); break;
|
||||
default : console.error( 'Abstraction unknown', abstraction );
|
||||
}
|
||||
},
|
||||
|
||||
use : function( node, program, namespace ) {
|
||||
if ( node.class && node.member ) {
|
||||
program.AddUse( namespace, program.GetClass( node.class ).GetMember( node.member ), this.CreateLocation( node.line ) );
|
||||
} else if ( node.member ) {
|
||||
program.AddUse( namespace, namespace.parent.GetMember( node.member ), this.CreateLocation( node.line ) );
|
||||
} else {
|
||||
program.AddUse( namespace, program.GetClass( node.class ), this.CreateLocation( node.line ) );
|
||||
}
|
||||
},
|
||||
|
||||
call : function( node, program, namespace ) {
|
||||
if ( node.class ) {
|
||||
program.AddCall( namespace, program.GetClass( node.class ).GetMethod( node.method ), this.CreateLocation( node.line ) );
|
||||
} else if ( node.function ) {
|
||||
program.AddCall( namespace, program.GetFunction( node.function ), this.CreateLocation( node.line ) );
|
||||
} else {
|
||||
program.AddCall( namespace, namespace.parent.GetMethod( node.method ), this.CreateLocation( node.line ) );
|
||||
}
|
||||
},
|
||||
|
||||
function : function( node, program, namespace ) {
|
||||
var functionModel = program.CreateFunction( node.name, this.CreateLocation( node.line ) );
|
||||
this.AddParams( functionModel, node, program );
|
||||
this.ParseContent( node.content, program, functionModel );
|
||||
},
|
||||
|
||||
CreateLocation : function( lineNumber ) {
|
||||
return new SHIFT.Location( this.fileName, lineNumber );
|
||||
},
|
||||
|
||||
AddParams : function( functionModel, node, program ) {
|
||||
if ( node.params ) {
|
||||
for ( var i = 0; i < node.params.length; i++ ) {
|
||||
program.AddUse( functionModel, program.GetClass( node.params[i] ), this.CreateLocation( node.line ) );
|
||||
}
|
||||
functionModel.params = node.params;
|
||||
}
|
||||
|
||||
if ( node.return ) {
|
||||
program.AddUse( functionModel, program.GetClass( node.return ), this.CreateLocation( node.line ) );
|
||||
functionModel.return = node.return;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,123 @@
|
||||
var program;
|
||||
var width;
|
||||
var height;
|
||||
var useSample = false;
|
||||
|
||||
function main() {
|
||||
|
||||
$( '#wrapper' ).height( $( window ).height() - $( '#header' ).height() - 35 );
|
||||
width = $( '#paper' ).width();
|
||||
height = $( '#paper' ).height();
|
||||
|
||||
SHIFT.FileViewer.Init();
|
||||
|
||||
// useSample = true;
|
||||
if ( useSample || getURLParams().sample ) {
|
||||
$( '#sample' ).show();
|
||||
sample();
|
||||
} else {
|
||||
SHIFT.FileViewer.ShowNavigation();
|
||||
program = SHIFT.Interpreter.CreateProgram( data );
|
||||
}
|
||||
|
||||
program.SetPaper( Raphael( 'paper', width, height ) );
|
||||
program.ShowInterface();
|
||||
|
||||
document.getElementById( 'paper' ).addEventListener( 'contextmenu', function( event ) {
|
||||
event.preventDefault();
|
||||
});
|
||||
document.getElementById( 'paper' ).addEventListener( 'selectstart', function( event ) {
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
function sample() {
|
||||
program = new SHIFT.Program();
|
||||
|
||||
// var class1 = program.CreateClass( 'class1', new SHIFT.Location( 'sample', 1 ) );
|
||||
// class1.CreateMethod( 'method', new SHIFT.Location( 'sample', 1 ), SHIFT.Visibility.Public );
|
||||
//
|
||||
// var class2 = program.CreateClass( 'class2', new SHIFT.Location( 'sample', 1 ) );
|
||||
// class2.CreateMethod( 'method', new SHIFT.Location( 'sample', 1 ), SHIFT.Visibility.Public );
|
||||
// class2.CreateMember( 'member', new SHIFT.Location( 'sample', 1 ), SHIFT.Visibility.Private );
|
||||
//
|
||||
// var class3 = program.CreateClass( 'class3', new SHIFT.Location( 'sample', 1 ) );
|
||||
// class3.CreateMethod( 'method', new SHIFT.Location( 'sample', 1 ), SHIFT.Visibility.Public );
|
||||
// class3.CreateMember( 'member', new SHIFT.Location( 'sample', 1 ), SHIFT.Visibility.Private );
|
||||
//
|
||||
// return;
|
||||
|
||||
// var connection = program.CreateClass( 'Connection' );
|
||||
// var use = program.CreateClass( 'Use' );
|
||||
// var call = program.CreateClass( 'Call' );
|
||||
// var inheritance = program.CreateClass( 'Inheritance' );
|
||||
// var instantiation = program.CreateClass( 'Instantiation' );
|
||||
// var association = program.CreateClass( 'Association' );
|
||||
//
|
||||
// program.AddInheritance( connection, use );
|
||||
// program.AddInheritance( connection, call );
|
||||
// program.AddInheritance( connection, inheritance );
|
||||
// program.AddInheritance( inheritance, instantiation );
|
||||
// program.AddInheritance( connection, association );
|
||||
//
|
||||
//
|
||||
// var connectable = program.CreateClass( 'Connectable' );
|
||||
// var object = program.CreateClass( 'Object' );
|
||||
// var variable = program.CreateClass( 'Variable' );
|
||||
// var member = program.CreateClass( 'Member' );
|
||||
// var func = program.CreateClass( 'Function' );
|
||||
// var method = program.CreateClass( 'Method' );
|
||||
// var clas = program.CreateClass( 'Class' );
|
||||
// var container = program.CreateClass( 'Container' );
|
||||
// var prog = program.CreateClass( 'Program' );
|
||||
//
|
||||
// program.AddInheritance( connectable, object );
|
||||
// program.AddInheritance( object, clas );
|
||||
// program.AddInheritance( object, func );
|
||||
// program.AddInheritance( object, variable );
|
||||
// program.AddInheritance( variable, member );
|
||||
// program.AddInheritance( func, method );
|
||||
// program.AddInheritance( container, clas );
|
||||
// program.AddInheritance( container, prog );
|
||||
//
|
||||
// program.AddInstantiation( container.CreateMember( 'objects' ), object );
|
||||
// program.AddInstantiation( container.CreateMember( 'connections' ), connection );
|
||||
// program.AddInstantiation( connectable.CreateMember( 'connections' ), connection );
|
||||
// program.AddInstantiation( connection.CreateMember( 'from' ), connectable );
|
||||
// program.AddInstantiation( connection.CreateMember( 'to' ), connectable );
|
||||
//
|
||||
// return;
|
||||
|
||||
var playerClass = program.CreateClass( 'Player', new SHIFT.Location( 'sample', 1 ) );
|
||||
var playerClassMethodDo = playerClass.CreateMethod( 'Do', new SHIFT.Location( 'sample', 3 ) );
|
||||
|
||||
var baseClass = program.CreateClass( 'Base', new SHIFT.Location( 'sample', 6 ) );
|
||||
|
||||
var gameClass = program.CreateClass( 'Game', new SHIFT.Location( 'sample', 8 ) );
|
||||
var baseGameInheritance = program.AddInheritance( baseClass, gameClass, new SHIFT.Location( 'sample', 8 ) );
|
||||
|
||||
var gameClassConstructor = gameClass.CreateMethod( 'Game', new SHIFT.Location( 'sample', 10 ) );
|
||||
var gameClassMethodInit = gameClass.CreateMethod( 'Init', new SHIFT.Location( 'sample', 14 ) );
|
||||
var gameClassMethodRun = gameClass.CreateMethod( 'Run', new SHIFT.Location( 'sample', 16 ) );
|
||||
var gameClassPlayerMember = gameClass.CreateMember( 'player', new SHIFT.Location( 'sample', 20 ) );
|
||||
gameClassPlayerMember.typename = 'Player';
|
||||
var gameClassPlayerMemberInstantiation = program.AddInstantiation( gameClassPlayerMember, playerClass, new SHIFT.Location( 'sample', 20 ) );
|
||||
|
||||
var gameClassMethodInitCall = program.AddCall( gameClassConstructor, gameClassMethodInit, new SHIFT.Location( 'sample', 11 ) );
|
||||
var gameClassPlayerMemberUse = program.AddUse( gameClassMethodRun, gameClassPlayerMember );
|
||||
var playerClassMethodDoCall = program.AddCall( gameClassMethodRun, playerClassMethodDo, new SHIFT.Location( 'sample', 17 ) );
|
||||
|
||||
var gameVariable = program.CreateVariable( 'game', new SHIFT.Location( 'sample', 23 ) );
|
||||
var gameVariableGameClassInstantiation = program.AddInstantiation( gameVariable, gameClass, new SHIFT.Location( 'sample', 23 ) );
|
||||
gameVariable.typename = 'Game';
|
||||
|
||||
var mainFunction = program.CreateFunction( 'main', new SHIFT.Location( 'sample', 25 ) );
|
||||
program.AddUse( mainFunction, program.GetClass( 'int' ), new SHIFT.Location( 'sample', 25 ) );
|
||||
var gameClassConstructorCall = program.AddCall( mainFunction, gameClassConstructor, new SHIFT.Location( 'sample', 26 ) );
|
||||
|
||||
var gameClassMethodRunCall = program.AddCall( mainFunction, gameClassMethodRun, new SHIFT.Location( 'sample', 28 ) );
|
||||
|
||||
program.AddUse( mainFunction, gameVariable, new SHIFT.Location( 'sample', 26 ) );
|
||||
program.AddUse( mainFunction, gameVariable, new SHIFT.Location( 'sample', 28 ) );
|
||||
program.AddUse( mainFunction, gameVariable, new SHIFT.Location( 'sample', 30 ) );
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
SHIFT.Member = function( name ) {
|
||||
SHIFT.Variable.call( this, name );
|
||||
|
||||
this.visibility = SHIFT.Visibility.Public;
|
||||
this.abstraction = SHIFT.Abstraction.None;
|
||||
}
|
||||
|
||||
SHIFT.Member.prototype = {
|
||||
__proto__ : SHIFT.Variable.prototype,
|
||||
|
||||
type : SHIFT.Types.Member,
|
||||
|
||||
dragable : false
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
SHIFT.Method = function( name ) {
|
||||
SHIFT.Function.call( this, name );
|
||||
|
||||
this.visibility = SHIFT.Visibility.Public;
|
||||
this.abstraction = SHIFT.Abstraction.None;
|
||||
}
|
||||
|
||||
SHIFT.Method.prototype = {
|
||||
__proto__ : SHIFT.Function.prototype,
|
||||
|
||||
type : SHIFT.Types.Method,
|
||||
|
||||
dragable : false,
|
||||
|
||||
CreateNode : function( paper, fromNode, toNode ) {
|
||||
var node = SHIFT.Function.prototype.CreateNode.call( this, paper, fromNode, toNode );
|
||||
if ( this.abstraction === SHIFT.Abstraction.PureVirtual ) {
|
||||
node[0].dash();
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
SetAbstraction : function( abstraction ) {
|
||||
this.abstraction = abstraction;
|
||||
if ( abstraction === SHIFT.Abstraction.Virtual || abstraction === SHIFT.Abstraction.PureVirtual ) {
|
||||
this.parent.CheckVirtualCall( this );
|
||||
}
|
||||
if ( abstraction === SHIFT.Abstraction.PureVirtual ) {
|
||||
this.parent.abstraction = SHIFT.Abstraction.PureVirtual;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
SHIFT.Object = function( name ) {
|
||||
SHIFT.Connectable.call( this );
|
||||
|
||||
this.name = name;
|
||||
|
||||
this.parent = null;
|
||||
this.node = null;
|
||||
this.location = null;
|
||||
|
||||
this.pos = new Vector;
|
||||
this.move = new Vector;
|
||||
|
||||
this.active = false;
|
||||
this.dragging = false;
|
||||
}
|
||||
|
||||
SHIFT.Object.prototype = {
|
||||
__proto__ : SHIFT.Connectable.prototype,
|
||||
|
||||
dragable : true,
|
||||
|
||||
color : SHIFT.Colors.dark,
|
||||
highlight : '#EC3636',
|
||||
|
||||
Show : function( paper, x, y ) {
|
||||
if ( !this.type.visible ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.node = this.CreateNode( paper, x, y );
|
||||
this.pos.set( x, y );
|
||||
|
||||
if ( this.dragable ) {
|
||||
this.node.drag( this.DragMove, this.DragStart, this.DragEnd, this, this, this );
|
||||
}
|
||||
|
||||
if ( !this.active ) {
|
||||
this.node[0].stroke( SHIFT.Colors.light );
|
||||
this.node[1].fill( SHIFT.Colors.light );
|
||||
if ( this.type === SHIFT.Types.Class && this.publics.length && !this.publicOpen ) {
|
||||
this.node[2].fill( SHIFT.Colors.light );
|
||||
}
|
||||
}
|
||||
|
||||
this.node[0].hover( this.HoverIn, this.HoverOut, this, this );
|
||||
this.node[1].hover( this.HoverIn, this.HoverOut, this, this );
|
||||
if ( this.type === SHIFT.Types.Class && this.publics.length && !this.publicOpen ) {
|
||||
this.node[2].hover( this.HoverIn, this.HoverOut, this, this );
|
||||
}
|
||||
|
||||
this.node[0].mousedown( this.MouseDown, this );
|
||||
this.node[1].mousedown( this.MouseDown, this );
|
||||
if ( this.type === SHIFT.Types.Class && this.publics.length && !this.publicOpen ) {
|
||||
this.node[2].mousedown( this.MouseDown, this );
|
||||
}
|
||||
|
||||
return this.node;
|
||||
},
|
||||
|
||||
CreateNode : function( paper, x, y ) {
|
||||
console.error( 'not implemented' );
|
||||
},
|
||||
|
||||
DragStart : function( x, y, event ) {
|
||||
if ( event.button === 2 ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.node.oldTransform = this.node[0].transform();
|
||||
this.move.set( 0, 0 );
|
||||
this.dragging = true;
|
||||
},
|
||||
|
||||
DragMove : function( dx, dy ) {
|
||||
if ( !this.dragging ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.move.set( dx, dy );
|
||||
this.node.transform( this.node.oldTransform + 't' + dx + ',' + dy );
|
||||
this.UpdateConnections( this.node.paper );
|
||||
},
|
||||
|
||||
DragEnd : function() {
|
||||
if ( !this.dragging ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.pos.addSelf( this.move );
|
||||
this.dragging = false;
|
||||
},
|
||||
|
||||
HoverIn : function() {
|
||||
if ( this.active ) {
|
||||
this.parent.HoverInHandler( this );
|
||||
}
|
||||
},
|
||||
|
||||
HoverOut : function() {
|
||||
if ( this.active ) {
|
||||
this.parent.HoverOutHandler( this );
|
||||
}
|
||||
},
|
||||
|
||||
HoverInHandler : function( obj ) {
|
||||
this.parent.HoverInHandler( obj );
|
||||
},
|
||||
|
||||
HoverOutHandler : function( obj ) {
|
||||
this.parent.HoverOutHandler( obj );
|
||||
},
|
||||
|
||||
Remove : function() {
|
||||
if ( this.node ) {
|
||||
this.node.remove();
|
||||
}
|
||||
this.node = null;
|
||||
},
|
||||
|
||||
Update : function( paper ) {
|
||||
this.Remove();
|
||||
this.Show( paper, this.pos.x, this.pos.y );
|
||||
},
|
||||
|
||||
Name : function() {
|
||||
var parentName = this.parent.Name();
|
||||
if ( parentName.length ) {
|
||||
return parentName + '::' + this.name;
|
||||
}
|
||||
return this.name;
|
||||
},
|
||||
|
||||
Hover : function() {
|
||||
if ( this.node ) {
|
||||
this.node[0].stroke( this.highlight );
|
||||
}
|
||||
},
|
||||
|
||||
Hovered : function() {
|
||||
if ( this.node ) {
|
||||
this.node[0].stroke( this.color );
|
||||
}
|
||||
},
|
||||
|
||||
LastParent : function() {
|
||||
if ( this.parent.type !== SHIFT.Types.Program ) {
|
||||
return this.parent.LastParent();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
NextParentWithNode : function() {
|
||||
if ( this.node ) {
|
||||
return this;
|
||||
} else if ( this.parent.NextParentWithNode ) {
|
||||
return this.parent.NextParentWithNode();
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
GetProgram : function() {
|
||||
if ( this.parent.type === SHIFT.Types.Program ) {
|
||||
return this.parent;
|
||||
}
|
||||
return this.parent.GetProgram();
|
||||
},
|
||||
|
||||
MouseDown : function( event ) {
|
||||
if ( event.button === 0 && this.active && this.location ) {
|
||||
SHIFT.FileViewer.ShowLocation( this.location );
|
||||
} else if ( event.button === 2 ) {
|
||||
if ( this.active ) {
|
||||
this.Fade();
|
||||
} else {
|
||||
this.Awake();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Awake : function() {
|
||||
this.active = true;
|
||||
this.node[0].stroke( this.color );
|
||||
this.node[1].fill( this.color );
|
||||
this.UpdateConnections( this.node.paper );
|
||||
},
|
||||
|
||||
Fade : function() {
|
||||
this.active = false;
|
||||
this.node[0].stroke( SHIFT.Colors.light );
|
||||
this.node[1].fill( SHIFT.Colors.light );
|
||||
this.UpdateConnections( this.node.paper );
|
||||
},
|
||||
|
||||
Open : function() {}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
SHIFT.Location = function( fileName, lineNumber ) {
|
||||
this.fileName = fileName;
|
||||
this.lineNumber = lineNumber
|
||||
}
|
||||
@@ -0,0 +1,238 @@
|
||||
SHIFT.Program = function() {
|
||||
SHIFT.Container.call( this );
|
||||
}
|
||||
|
||||
SHIFT.Program.prototype = {
|
||||
__proto__ : SHIFT.Container.prototype,
|
||||
|
||||
type : SHIFT.Types.Program,
|
||||
|
||||
SetPaper : function( paper ) {
|
||||
this.paper = paper;
|
||||
},
|
||||
|
||||
GetClass : function( name ) {
|
||||
var names = name.split( '::' );
|
||||
var obj;
|
||||
if ( names.length === 2 ) {
|
||||
var classModel = this.FindBy( this.objects, 'name', names[0] );
|
||||
if ( !classModel ) {
|
||||
classModel = this.Get( SHIFT.Class, names[0] );
|
||||
}
|
||||
obj = this.FindBy( classModel.objects, 'name', names[1] );
|
||||
if ( obj ) {
|
||||
return obj;
|
||||
} else {
|
||||
return classModel.Get( SHIFT.Class, names[1] );
|
||||
}
|
||||
}
|
||||
|
||||
obj = this.FindBy( this.objects, 'name', name );
|
||||
if ( !obj ) {
|
||||
var classes = this.FindAllBy( this.objects, 'type', SHIFT.Types.Class );
|
||||
for ( var i = 0; i < classes.length; i++ ) {
|
||||
obj = this.FindBy( classes[i].objects, 'name', name );
|
||||
if ( obj ) {
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
return this.Get( SHIFT.Class, name );
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
GetVariable : function( name ) {
|
||||
return this.Get( SHIFT.Variable, name );
|
||||
},
|
||||
|
||||
GetFunction : function( name ) {
|
||||
return this.Get( SHIFT.Function, name );
|
||||
},
|
||||
|
||||
CreateClass : function( name, location ) {
|
||||
return this.Create( SHIFT.Class, name, location );
|
||||
},
|
||||
|
||||
CreateVariable : function( name, location ) {
|
||||
return this.Create( SHIFT.Variable, name, location );
|
||||
},
|
||||
|
||||
CreateFunction : function( name, location ) {
|
||||
return this.Create( SHIFT.Function, name, location );
|
||||
},
|
||||
|
||||
AddCall : function( from, to, location ) {
|
||||
if ( from !== to ) {
|
||||
return this.Connect( SHIFT.Call, from, to, location );
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
AddInheritance : function( from, to, location ) {
|
||||
return this.Connect( SHIFT.Inheritance, from, to, location );
|
||||
},
|
||||
|
||||
AddInstantiation : function( from, to, location ) {
|
||||
return this.Connect( SHIFT.Instantiation, from, to, location );
|
||||
},
|
||||
|
||||
AddUse : function( from, to, location ) {
|
||||
return this.Connect( SHIFT.Use, from, to, location );
|
||||
},
|
||||
|
||||
AddAssociation : function( from, to ) {
|
||||
var typename = SHIFT.Association.prototype.type.name;
|
||||
var name = typename + ':' + from.Name() + '->' + to.Name();
|
||||
var obj = this.FindBy( this.connections, 'name', name );
|
||||
if ( !obj ) {
|
||||
obj = this.FindBy( this.connections, 'name', typename + ':' + to.Name() + '->' + from.Name() );
|
||||
}
|
||||
if ( !obj ) {
|
||||
obj = new SHIFT.Association( name, from, to );
|
||||
this.connections.push( obj );
|
||||
}
|
||||
return obj;
|
||||
},
|
||||
|
||||
ShowInterface : function() {
|
||||
var paper = this.paper;
|
||||
paper.clear();
|
||||
|
||||
for ( var i = 0; i < this.objects.length; i++ ) {
|
||||
this.objects[i].Show(
|
||||
paper,
|
||||
randInt( 50, width - 50 ),
|
||||
randInt( 50, height - 50 )
|
||||
);
|
||||
}
|
||||
|
||||
for ( var i = 0; i < this.connections.length; i++ ) {
|
||||
if ( this.connections[i].type !== SHIFT.Types.Association ) {
|
||||
this.connections[i].Show( paper );
|
||||
}
|
||||
}
|
||||
|
||||
this.ShowMenu( paper );
|
||||
},
|
||||
|
||||
ShowMenu : function( paper ) {
|
||||
var setTypesVisible = function( types ) {
|
||||
return function( checked ) {
|
||||
for ( var i = 0; i < types.length; i++ ) {
|
||||
SHIFT.Types[types[i]].visible = checked;
|
||||
}
|
||||
program.Update();
|
||||
set.toFront();
|
||||
}
|
||||
}
|
||||
|
||||
paper.setStart();
|
||||
|
||||
var rect = paper.rect( -10, -10, 710, 170, 5 ).box();
|
||||
var menu = paper.text( 340, 147, 'legend & filters' ).code( 20 );
|
||||
|
||||
// class
|
||||
paper.checkbox( 20, 25, 16, true ).click( setTypesVisible( ['Class'] ) );
|
||||
paper.rect( 38, 10, 260, 30, 5 ).box();
|
||||
text = paper.text( 48, 27, 'type & class & namespace' ).code( 18 );
|
||||
text.transform( 'T' + text.getBBox().width / 2 + ' 0' );
|
||||
|
||||
// variable
|
||||
paper.checkbox( 20, 65, 16, true ).click( setTypesVisible( ['Variable', 'Member'] ) );
|
||||
paper.rect( 40, 53, 150, 22 ).box();
|
||||
text = paper.text( 48, 66, 'variable & member' ).code( 14 );
|
||||
text.transform( 'T' + text.getBBox().width / 2 + ' 0' );
|
||||
|
||||
// function
|
||||
paper.checkbox( 20, 105, 16, true ).click( setTypesVisible( ['Function', 'Method'] ) );
|
||||
paper.ellipse( 117, 105, 80, 15 ).box();
|
||||
text = paper.text( 48, 107, 'function & method' ).code( 14 );
|
||||
text.transform( 'T' + text.getBBox().width / 2 + ' 0' );
|
||||
|
||||
// use
|
||||
paper.checkbox( 270, 65, 16, true ).click( setTypesVisible( ['Use'] ) );
|
||||
paper.path( 'M 340 62 l 50 8' ).line( SHIFT.Colors.light ).thin();
|
||||
text = paper.text( 298, 65, 'use' ).code( 16 );
|
||||
text.transform( 'T' + text.getBBox().width / 2 + ' 0' );
|
||||
|
||||
// call
|
||||
paper.checkbox( 270, 105, 16, true ).click( setTypesVisible( ['Call'] ) );
|
||||
var call = paper.wave( paper.rect( 340, 95, 5, 5 ).stroke( 'white' ), paper.rect( 410, 105, 5, 5 ).stroke( 'white' ) ).line( SHIFT.Colors.light );
|
||||
var end = call.points[1];
|
||||
paper.arrow( end.x, end.y, end.i ).line( SHIFT.Colors.light );
|
||||
text = paper.text( 298, 105, 'call' ).code( 16 );
|
||||
text.transform( 'T' + text.getBBox().width / 2 + ' 0' );
|
||||
|
||||
// inheritance
|
||||
paper.checkbox( 470, 25, 16, true ).click( setTypesVisible( ['Inheritance'] ) );
|
||||
paper.arrow2( paper.rect( 660, 15, 5, 5 ).stroke( 'white' ), paper.rect( 600, 25, 5, 5 ).stroke( 'white' ) ).line( SHIFT.Colors.light );
|
||||
text = paper.text( 498, 25, 'inheritance' ).code( 16 );
|
||||
text.transform( 'T' + text.getBBox().width / 2 + ' 0' );
|
||||
|
||||
// instantiation
|
||||
paper.checkbox( 470, 65, 16, true ).click( setTypesVisible( ['Instantiation'] ) );
|
||||
paper.arrow2( paper.rect( 680, 55, 5, 5 ).stroke( 'white' ), paper.rect( 620, 65, 5, 5 ).stroke( 'white' ) ).line( SHIFT.Colors.light ).dash();
|
||||
text = paper.text( 498, 65, 'instantiation' ).code( 16 );
|
||||
text.transform( 'T' + text.getBBox().width / 2 + ' 0' );
|
||||
|
||||
// association
|
||||
paper.checkbox( 470, 105, 16, true ).click( setTypesVisible( ['Association'] ) );
|
||||
paper.path( 'M 610 102 l 50 8' ).line( 'lightblue', 4 );
|
||||
text = paper.text( 498, 105, 'association' ).code( 16 );
|
||||
text.transform( 'T' + text.getBBox().width / 2 + ' 0' );
|
||||
|
||||
var set = paper.setFinish();
|
||||
set.toggled = false;
|
||||
|
||||
function handler() {
|
||||
set.toggled = !set.toggled;
|
||||
var y = rect.getBBox().height - 40;
|
||||
set.transform( '...t 0 ' + ( set.toggled ? -y : y ) ).toFront();
|
||||
}
|
||||
|
||||
rect.click( handler );
|
||||
menu.click( handler );
|
||||
handler();
|
||||
},
|
||||
|
||||
Update : function() {
|
||||
var paper = this.paper;
|
||||
|
||||
for ( var i = 0; i < this.objects.length; i++ ) {
|
||||
this.objects[i].Update( paper );
|
||||
}
|
||||
|
||||
for ( var i = 0; i < this.connections.length; i++ ) {
|
||||
if ( this.connections[i].type !== SHIFT.Types.Association ) {
|
||||
this.connections[i].Update( paper );
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Name : function() {
|
||||
return '';
|
||||
},
|
||||
|
||||
HoverInHandler : function( obj ) {
|
||||
obj.Hover();
|
||||
var connections = this.GetConnections( obj );
|
||||
|
||||
for ( var i = 0; i < connections.length; i++ ) {
|
||||
connections[i].Hover( false );
|
||||
}
|
||||
},
|
||||
|
||||
HoverOutHandler : function( obj ) {
|
||||
obj.Hovered();
|
||||
var connections = this.GetConnections( obj );
|
||||
|
||||
for ( var i = 0; i < connections.length; i++ ) {
|
||||
connections[i].Hovered();
|
||||
}
|
||||
},
|
||||
|
||||
GetConnections : function( obj ) {
|
||||
var connections = this.FindAllBy( this.connections, 'from', obj );
|
||||
return connections.concat( this.FindAllBy( this.connections, 'to', obj ) );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
var SHIFT = {
|
||||
Types : {
|
||||
Variable : { name : 'variable', visible : true },
|
||||
Use : { name : 'use', visible : true },
|
||||
Function : { name : 'function', visible : true },
|
||||
Call : { name : 'call', visible : true },
|
||||
Class : { name : 'class', visible : true },
|
||||
Member : { name : 'member', visible : true },
|
||||
Method : { name : 'method', visible : true },
|
||||
Inheritance : { name : 'inheritance', visible : true },
|
||||
Instantiation : { name : 'instantiation', visible : true },
|
||||
Association : { name : 'association', visible : true },
|
||||
Program : null,
|
||||
},
|
||||
|
||||
Visibility : {
|
||||
None : 0,
|
||||
Private : 1,
|
||||
Protected : 2,
|
||||
Public : 3
|
||||
},
|
||||
|
||||
Abstraction : {
|
||||
None : 0,
|
||||
Static : 1,
|
||||
Virtual : 2,
|
||||
PureVirtual : 3
|
||||
},
|
||||
|
||||
Colors : {
|
||||
dark : '#555',
|
||||
light : '#AAA'
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
SHIFT.Use = function( name, user, used ) {
|
||||
SHIFT.Connection.call( this, name, user, used );
|
||||
}
|
||||
|
||||
SHIFT.Use.prototype = {
|
||||
__proto__ : SHIFT.Connection.prototype,
|
||||
|
||||
type : SHIFT.Types.Use,
|
||||
|
||||
CreateNode : function( paper, fromNode, toNode, sameClass ) {
|
||||
if ( sameClass ) {
|
||||
return paper.bow( fromNode, toNode, 1 ).line( this.color ).thin();
|
||||
} else {
|
||||
return paper.connection( fromNode, toNode ).line( this.color ).thin();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,273 @@
|
||||
extend( Raphael.el, {
|
||||
box : function() {
|
||||
return this.attr({
|
||||
fill : 'white',
|
||||
stroke : '#555',
|
||||
'stroke-width' : 1.5
|
||||
});
|
||||
},
|
||||
|
||||
line : function( color, width ) {
|
||||
return this.attr({
|
||||
'stroke-width' : width || 1.5,
|
||||
stroke : color
|
||||
});
|
||||
},
|
||||
|
||||
thick : function() {
|
||||
return this.attr({
|
||||
'stroke-width' : 3
|
||||
});
|
||||
},
|
||||
|
||||
thin : function() {
|
||||
return this.attr({
|
||||
'stroke-width' : 1
|
||||
});
|
||||
},
|
||||
|
||||
dash : function() {
|
||||
return this.attr({
|
||||
'stroke-dasharray' : ['- ']
|
||||
});
|
||||
},
|
||||
|
||||
code : function( size ) {
|
||||
return this.attr({
|
||||
font : size + 'px Consolas, monospace',
|
||||
fill : '#555'
|
||||
});
|
||||
},
|
||||
|
||||
stroke : function( color ) {
|
||||
this.attr({
|
||||
stroke : 'rgba(0,0,0,1)'
|
||||
});
|
||||
return this.attr({
|
||||
stroke : color
|
||||
});
|
||||
},
|
||||
|
||||
fill : function( color ) {
|
||||
return this.attr({
|
||||
fill : color
|
||||
});
|
||||
},
|
||||
|
||||
color : function( color ) {
|
||||
this.stroke( color );
|
||||
this.fill( color );
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
Raphael.st.add = function( name ) {
|
||||
this[name] = function() {
|
||||
var args = arguments;
|
||||
return this.forEach( function( el ) {
|
||||
el[name].apply( el, args );
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
Raphael.st.add( 'stroke' );
|
||||
Raphael.st.add( 'fill' );
|
||||
Raphael.st.add( 'color' );
|
||||
Raphael.st.add( 'dash' );
|
||||
Raphael.st.add( 'thin' );
|
||||
Raphael.st.add( 'thick' );
|
||||
Raphael.st.add( 'line' );
|
||||
|
||||
extend( Raphael.fn, {
|
||||
getPoints : function( obj ) {
|
||||
var bb = obj.getBBox();
|
||||
return [
|
||||
{x : bb.x + bb.width / 2, y : bb.y - 1, i : 0},
|
||||
{x : bb.x2 + 1, y : bb.y + bb.height / 2, i : 1},
|
||||
{x : bb.x + bb.width / 2, y : bb.y2 + 1, i : 2},
|
||||
{x : bb.x - 1, y : bb.y + bb.height / 2, i : 3}
|
||||
];
|
||||
},
|
||||
|
||||
connectionPoints : function( obj1, obj2 ) {
|
||||
var p1 = this.getPoints( obj1 );
|
||||
var p2 = this.getPoints( obj2 );
|
||||
|
||||
var vec = new Vector;
|
||||
var min = Infinity, a, b;
|
||||
for ( var i = 0; i < 4; i++ ) {
|
||||
for ( var j = 0; j < 4; j++ ) {
|
||||
vec.copy( p1[i] ).subSelf( p2[j] );
|
||||
var dist = vec.normSquared();
|
||||
if ( dist < min ) {
|
||||
min = dist;
|
||||
a = p1[i];
|
||||
b = p2[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [a, b];
|
||||
},
|
||||
|
||||
shortestTo : function( p, q ) {
|
||||
var vec = new Vector;
|
||||
var min = Infinity, r;
|
||||
for ( var i = 0; i < 4; i++ ) {
|
||||
vec.copy( p ).subSelf( q[i] );
|
||||
var d = vec.normSquared();
|
||||
if ( d < min ) {
|
||||
min = d;
|
||||
r = q[i];
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
shortestPoints : function( obj1, obj2 ) {
|
||||
var bb1 = obj1.getBBox();
|
||||
var bb2 = obj2.getBBox();
|
||||
|
||||
var p1 = { x : 0, y : 0, i : 0 };
|
||||
var p2 = { x : 0, y : 0, i : 0 };
|
||||
|
||||
var x1 = Math.max( bb1.x, bb2.x );
|
||||
var x2 = Math.min( bb1.x2, bb2.x2 );
|
||||
|
||||
if ( x1 < x2 ) {
|
||||
p1.x = p2.x = ( x1 + x2 ) / 2;
|
||||
} else if ( bb1.x2 === x2 ) {
|
||||
p1.x = x2;
|
||||
p2.x = x1;
|
||||
} else {
|
||||
p1.x = x1;
|
||||
p2.x = x2;
|
||||
}
|
||||
|
||||
var y1 = Math.max( bb1.y, bb2.y );
|
||||
var y2 = Math.min( bb1.y2, bb2.y2 );
|
||||
|
||||
if ( y1 < y2 ) {
|
||||
p1.y = p2.y = ( y1 + y2 ) / 2;
|
||||
} else if ( bb1.y2 === y2 ) {
|
||||
p1.y = y2;
|
||||
p2.y = y1;
|
||||
} else {
|
||||
p1.y = y1;
|
||||
p2.y = y2;
|
||||
}
|
||||
|
||||
return [p1, p2];
|
||||
},
|
||||
|
||||
wave : function( obj1, obj2 ) {
|
||||
var p = this.connectionPoints( obj1, obj2 );
|
||||
var x2, y2, x3, y3;
|
||||
if ( p[0].i % 2 == 0 ) {
|
||||
x2 = p[0].x;
|
||||
y2 = ( p[0].y + p[1].y ) / 2;
|
||||
} else {
|
||||
x2 = ( p[0].x + p[1].x ) / 2;
|
||||
y2 = p[0].y;
|
||||
}
|
||||
if ( p[1].i % 2 == 0 ) {
|
||||
x3 = p[1].x;
|
||||
y3 = ( p[0].y + p[1].y ) / 2;
|
||||
} else {
|
||||
x3 = ( p[0].x + p[1].x ) / 2;
|
||||
y3 = p[1].y;
|
||||
}
|
||||
var path = this.path( ['M', p[0].x, p[0].y, 'C', x2, y2, x3, y3, p[1].x, p[1].y].join( ' ' ) );
|
||||
path.points = p;
|
||||
return path;
|
||||
},
|
||||
|
||||
bow : function( obj1, obj2, f ) {
|
||||
var p1 = this.getPoints( obj1 );
|
||||
var p2 = this.getPoints( obj2 );
|
||||
if ( p1[1].y < p2[1].y ) {
|
||||
p1 = p1[3];
|
||||
p2 = p2[3];
|
||||
f *= -1;
|
||||
} else {
|
||||
p1 = p1[1];
|
||||
p2 = p2[1];
|
||||
}
|
||||
var mid = new Vector().copy( p1 ).addSelf( p2 ).divSelf( 2 );
|
||||
mid.x += clamp( f * Math.abs( p1.y - p2.y ), -200, 200 );
|
||||
var bow = this.path( ['M', p1.x, p1.y, 'S', mid.x, mid.y, p2.x, p2.y].join( ' ' ) );
|
||||
bow.points = [p1, p2];
|
||||
return bow;
|
||||
},
|
||||
|
||||
arrow : function( x, y, i ) {
|
||||
arrow = [
|
||||
['l', -5, -10, 'm', 10, 0, 'l', -5, 10],
|
||||
['l', 10, 5, 'm', 0, -10, 'l', -10, 5],
|
||||
['l', 5, 10, 'm', -10, 0, 'l', 5, -10],
|
||||
['l', -10, -5, 'm', 0, 10, 'l', 10, -5]
|
||||
];
|
||||
return this.path( ['M', x, y].concat( arrow[i] ).join( ' ' ) );
|
||||
},
|
||||
|
||||
arrow2 : function( obj1, obj2 ) {
|
||||
var p = this.connectionPoints( obj2, obj1 );
|
||||
var vec = new Vector().copy( p[1] ).subSelf( p[0] );
|
||||
var l = vec.norm();
|
||||
var r = vec.angle() / Math.PI * 180;
|
||||
var x = 20;
|
||||
var y = 10;
|
||||
var path = this.path( ['M', 0, 0, 'l', l - x, 0, 0, -y, x, y, -x, y, 0, -y].join( ' ' ) );
|
||||
path.transform( ['R', r, 0, 0, 'T', p[0].x, p[0].y].join( ' ' ) );
|
||||
return path;
|
||||
},
|
||||
|
||||
connection : function( obj1, obj2 ) {
|
||||
var p = this.connectionPoints( obj1, obj2 );
|
||||
return this.path( ['M', p[1].x, p[1].y, 'L', p[0].x, p[0].y].join( ' ' ) );
|
||||
},
|
||||
|
||||
shortest : function( obj1, obj2 ) {
|
||||
var p = this.shortestPoints( obj1, obj2 );
|
||||
return this.path( ['M', p[1].x, p[1].y, 'L', p[0].x, p[0].y].join( ' ' ) );
|
||||
},
|
||||
|
||||
shortest2 : function( obj1, obj2 ) {
|
||||
var p = this.shortestPoints( obj1, obj2 );
|
||||
p[1] = this.shortestTo( p[0], this.getPoints( obj2 ) );
|
||||
return this.path( ['M', p[1].x, p[1].y, 'L', p[0].x, p[0].y].join( ' ' ) );
|
||||
},
|
||||
|
||||
checkbox : function( x, y, size, checked ) {
|
||||
var s = size;
|
||||
x -= Math.floor( s / 2 );
|
||||
y -= Math.floor( s / 2 );
|
||||
|
||||
var rect = this.rect( x, y, s, s ).attr({ fill : 'rgba(0,0,0,0)' });
|
||||
var path = this.path( ['M', x, y, 'l', s, s, 'm', -s, 0, 'l', s, -s].join( ' ' ) );
|
||||
if ( !checked ) {
|
||||
path.hide();
|
||||
}
|
||||
|
||||
var handler = null;
|
||||
var set = this.set().push(rect, path);
|
||||
set.line( SHIFT.Colors.dark );
|
||||
set.click( function() {
|
||||
checked = !checked;
|
||||
checked ? path.show() : path.hide();
|
||||
if ( handler ) {
|
||||
handler( checked )
|
||||
}
|
||||
});
|
||||
|
||||
set.click = function( callback ) {
|
||||
handler = callback;
|
||||
return this;
|
||||
}
|
||||
set.hover( function() {
|
||||
set.stroke( SHIFT.Colors.light );
|
||||
}, function() {
|
||||
set.stroke( SHIFT.Colors.dark );
|
||||
});
|
||||
return set;
|
||||
}
|
||||
})
|
||||
@@ -0,0 +1,169 @@
|
||||
function bind(scope, fn) {
|
||||
|
||||
if ( fn ) {
|
||||
|
||||
return function() {
|
||||
|
||||
fn.apply(scope, arguments);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function extend(destination, source) {
|
||||
|
||||
for (var key in source) {
|
||||
|
||||
if (source.hasOwnProperty(key)) {
|
||||
|
||||
destination[key] = source[key];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return destination;
|
||||
|
||||
};
|
||||
|
||||
function log() {
|
||||
|
||||
console.log.apply(console, arguments);
|
||||
|
||||
};
|
||||
|
||||
function clamp( x, a, b ) {
|
||||
|
||||
return x ? x < a ? a : x > b ? b : x : a;
|
||||
|
||||
};
|
||||
|
||||
function map( x, a1, a2, b1, b2 ) {
|
||||
|
||||
return ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ) + b1;
|
||||
|
||||
};
|
||||
|
||||
function checkAngle( angle ) {
|
||||
|
||||
if ( angle > Math.PI ) {
|
||||
|
||||
angle -= 2 * Math.PI;
|
||||
|
||||
} else if ( angle <= -Math.PI ) {
|
||||
|
||||
angle += 2 * Math.PI;
|
||||
|
||||
}
|
||||
|
||||
return angle;
|
||||
|
||||
};
|
||||
|
||||
function rand( min, max ) {
|
||||
|
||||
min = min || 0;
|
||||
max = max || 1;
|
||||
|
||||
return Math.random() * (max - min) + min;
|
||||
|
||||
};
|
||||
|
||||
function randInt( min, max ) {
|
||||
|
||||
return Math.floor( rand( min, max ) );
|
||||
|
||||
};
|
||||
|
||||
function randSign() {
|
||||
|
||||
return Math.random() > 0.5 ? 1 : -1;
|
||||
|
||||
};
|
||||
|
||||
function randBool() {
|
||||
|
||||
return Math.random() > 0.5;
|
||||
|
||||
};
|
||||
|
||||
window.TAU = 2 * Math.PI;
|
||||
|
||||
function toRad( deg ) {
|
||||
|
||||
return deg * TAU / 360;
|
||||
|
||||
};
|
||||
|
||||
function toDeg( rad ) {
|
||||
|
||||
return rad / TAU * 360;
|
||||
|
||||
};
|
||||
|
||||
Array.prototype.forEachApply = function( fn, a ) {
|
||||
|
||||
this.forEach( function( e ) {
|
||||
|
||||
e[fn].call( e, a );
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
Array.prototype.clone = function() {
|
||||
|
||||
return this.concat();
|
||||
|
||||
};
|
||||
|
||||
Array.prototype.shuffle = function() {
|
||||
|
||||
var i = this.length, j, swap;
|
||||
|
||||
while ( i-- > 0 ) {
|
||||
|
||||
j = Math.floor( Math.random() * ( i + 1 ) );
|
||||
|
||||
swap = this[i];
|
||||
this[i] = this[j];
|
||||
this[j] = swap;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
Array.max = function( array ) {
|
||||
|
||||
return Math.max.apply( Math, array );
|
||||
|
||||
};
|
||||
|
||||
Array.min = function( array ) {
|
||||
|
||||
return Math.min.apply( Math, array );
|
||||
|
||||
};
|
||||
|
||||
function getURLParams() {
|
||||
|
||||
var params = {},
|
||||
floatRegex = /^[-+]?\d*\.?\d+$/,
|
||||
results = window.location.href.match( /[^?&#]*=[^&#]*/g ) || [],
|
||||
a, i;
|
||||
|
||||
for ( i = 0; i < results.length; i++ ) {
|
||||
|
||||
a = results[i].split('=');
|
||||
|
||||
params[a[0]] = floatRegex.test( a[1] ) ? parseFloat( a[1] ) : a[1];
|
||||
|
||||
}
|
||||
|
||||
return params;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,232 @@
|
||||
var Vector = function(x, y) {
|
||||
|
||||
return this.set(
|
||||
x || 0,
|
||||
y || 0
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
Vector.prototype = {
|
||||
|
||||
set: function(x, y) {
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
copy: function(vector) {
|
||||
|
||||
return this.set(
|
||||
vector.x,
|
||||
vector.y
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
clone: function() {
|
||||
|
||||
return new Vector(
|
||||
this.x,
|
||||
this.y
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
add: function(vector) {
|
||||
|
||||
return new Vector(
|
||||
this.x + vector.x,
|
||||
this.y + vector.y
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
addSelf: function(vector) {
|
||||
|
||||
this.x += vector.x;
|
||||
this.y += vector.y;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
sub: function(vector) {
|
||||
|
||||
return new Vector(
|
||||
this.x - vector.x,
|
||||
this.y - vector.y
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
subSelf: function(vector) {
|
||||
|
||||
this.x -= vector.x;
|
||||
this.y -= vector.y;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
mul: function(value) {
|
||||
|
||||
return new Vector(
|
||||
this.x * value,
|
||||
this.y * value
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
mulSelf: function(value) {
|
||||
|
||||
this.x *= value;
|
||||
this.y *= value;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
div: function(value) {
|
||||
|
||||
if (!value) {
|
||||
|
||||
return new Vector();
|
||||
|
||||
}
|
||||
|
||||
return new Vector(
|
||||
this.x / value,
|
||||
this.y / value
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
divSelf: function(value) {
|
||||
|
||||
if (value) {
|
||||
|
||||
this.x /= value;
|
||||
this.y /= value;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
dot: function(vector) {
|
||||
|
||||
return (this.x * vector.x + this.y * vector.y);
|
||||
|
||||
},
|
||||
|
||||
normSquared: function() {
|
||||
|
||||
return (this.x * this.x + this.y * this.y);
|
||||
|
||||
},
|
||||
|
||||
norm: function() {
|
||||
|
||||
return Math.sqrt(this.normSquared());
|
||||
|
||||
},
|
||||
|
||||
normalize: function() {
|
||||
|
||||
return this.div(this.norm());
|
||||
|
||||
},
|
||||
|
||||
normalizeSelf: function() {
|
||||
|
||||
return this.divSelf(this.norm());
|
||||
|
||||
},
|
||||
|
||||
clamp: function(value) {
|
||||
|
||||
if (this.normSquared() > value * value) {
|
||||
|
||||
return this.normalize().mul(value);
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
clampSelf: function(value) {
|
||||
|
||||
if (this.normSquared() > value * value) {
|
||||
|
||||
return this.normalizeSelf().mulSelf(value);
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
angle: function(vector) {
|
||||
|
||||
if (vector) {
|
||||
|
||||
return Math.acos(this.dot(vector) / this.norm() / vector.norm());
|
||||
|
||||
} else {
|
||||
|
||||
return Math.atan2(this.y, this.x);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
rotate: function(angle) {
|
||||
|
||||
return this.clone().rotateSelf(angle);
|
||||
|
||||
},
|
||||
|
||||
rotateSelf: function(angle) {
|
||||
|
||||
if ( !angle ) {
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
return this.set(
|
||||
Math.cos(angle) * this.x - Math.sin(angle) * this.y,
|
||||
Math.sin(angle) * this.x + Math.cos(angle) * this.y
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
string: function() {
|
||||
|
||||
return '( ' + this.x + ' | ' + this.y + ' )';
|
||||
|
||||
},
|
||||
|
||||
log: function() {
|
||||
|
||||
console.log( this.string() );
|
||||
|
||||
},
|
||||
|
||||
getData : function() {
|
||||
|
||||
return { x : this.x, y : this.y };
|
||||
|
||||
},
|
||||
|
||||
length : function() {
|
||||
return Math.sqrt( this.x * this.x + this.y * this.y);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
SHIFT.Variable = function( name ) {
|
||||
SHIFT.Object.call( this, name );
|
||||
|
||||
this.typename = '';
|
||||
}
|
||||
|
||||
SHIFT.Variable.prototype = {
|
||||
__proto__ : SHIFT.Object.prototype,
|
||||
|
||||
type : SHIFT.Types.Variable,
|
||||
|
||||
CreateNode : function( paper, x, y ) {
|
||||
y += 11;
|
||||
var name = this.typename.length ? this.typename + ' ' + this.name : this.name;
|
||||
var text = paper.text( x, y + 1, name ).code( 14 );
|
||||
var bb = text.getBBox();
|
||||
var rect = paper.rect( x - bb.width / 2 - 8, y - bb.height / 2 - 5, bb.width + 16, bb.height + 8 ).box();
|
||||
text.toFront();
|
||||
return paper.set().push( rect, text );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
body {
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
#header {
|
||||
height: 30px;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
#header div {
|
||||
margin-right: 5px;
|
||||
float: left;
|
||||
padding: 5px 8px;
|
||||
border: 2px #555 solid;
|
||||
border-radius: 5px;
|
||||
font-family: Consolas, monospace;
|
||||
font-size: 10pt;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
#header div:hover {
|
||||
border-color: #AAA;
|
||||
}
|
||||
|
||||
#header div.selected {
|
||||
border-color: #EC3636;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
margin: 0 10px;
|
||||
border: 2px solid #555;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
#files {
|
||||
float: left;
|
||||
height: 100%;
|
||||
width: 35%;
|
||||
overflow: auto;
|
||||
border-right: 2px solid #555;
|
||||
}
|
||||
|
||||
#files > * {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#paper {
|
||||
float: left;
|
||||
height: 100%;
|
||||
width: 64%;
|
||||
}
|
||||
|
||||
.syntaxhighlighter {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter .line.highlighted.alt1,
|
||||
.syntaxhighlighter .line.highlighted.alt2 {
|
||||
background-color: #ABF8AB !important;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef _ARTIFICIAL_
|
||||
#define _ARTIFICIAL_
|
||||
|
||||
#include "player.h"
|
||||
|
||||
class ArtificialPlayer : public Player {
|
||||
public:
|
||||
ArtificialPlayer( Field::Token token, const std::string& name )
|
||||
: Player( token, name ) {
|
||||
}
|
||||
|
||||
virtual Field::Move Turn( const Field& field ) const {
|
||||
srand( static_cast<unsigned int>( time( NULL ) ) );
|
||||
Field fakeField = field.Clone();
|
||||
Node node = MinMax( fakeField, token_ );
|
||||
return node.move;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Node {
|
||||
Field::Move move;
|
||||
int value;
|
||||
};
|
||||
|
||||
Node MinMax( Field& field, Field::Token token ) const {
|
||||
Node node;
|
||||
node.value = -10000;
|
||||
|
||||
Field::Move move;
|
||||
int sameMove;
|
||||
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
move.row = i;
|
||||
|
||||
for ( int j = 0; j < 3; j++ ) {
|
||||
move.col = j;
|
||||
|
||||
if ( !field.IsEmpty( move ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
field.MakeMove( move, token );
|
||||
|
||||
int turnValue = Evaluate( field, token );
|
||||
if ( !turnValue && !field.IsFull() ) {
|
||||
turnValue = -MinMax( field, Field::Opponent( token ) ).value;
|
||||
}
|
||||
|
||||
field.ClearMove( move );
|
||||
|
||||
if ( turnValue > node.value ) {
|
||||
node.move = move;
|
||||
node.value = turnValue;
|
||||
sameMove = 1;
|
||||
} else if ( turnValue == node.value ) {
|
||||
sameMove++;
|
||||
if ( rand() % sameMove == 0 ) {
|
||||
node.move = move;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
int Evaluate( const Field& field, Field::Token token ) const {
|
||||
if ( field.SameInRow( token, 3 ) ) {
|
||||
return 2;
|
||||
} else if ( field.SameInRow( Field::Opponent( token ), 2 ) ) {
|
||||
return -1;
|
||||
} else if ( field.SameInRow( token, 2 ) > 1 ) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _ARTIFICIAL_
|
||||
@@ -0,0 +1,147 @@
|
||||
#ifndef _FIELD_
|
||||
#define _FIELD_
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
class Field {
|
||||
public:
|
||||
enum Token {
|
||||
None = 0,
|
||||
PlayerA = 1,
|
||||
PlayerB = 4
|
||||
};
|
||||
|
||||
static Token Opponent( Token token ) {
|
||||
assert( token != None );
|
||||
if ( token == PlayerA ) {
|
||||
return PlayerB;
|
||||
} else {
|
||||
return PlayerA;
|
||||
}
|
||||
}
|
||||
|
||||
struct Move {
|
||||
int row;
|
||||
int col;
|
||||
};
|
||||
|
||||
Field()
|
||||
: left_( 9 ) {
|
||||
grid_ = new Token* [3];
|
||||
for ( int i = 0; i < 3 ; i++ ) {
|
||||
grid_[i] = new Token[3];
|
||||
}
|
||||
}
|
||||
|
||||
~Field() {
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
delete grid_[i];
|
||||
}
|
||||
delete [] grid_;
|
||||
}
|
||||
|
||||
Field Clone() const {
|
||||
Field field;
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
for ( int j = 0; j < 3; j++ ) {
|
||||
field.grid_[i][j] = grid_[i][j];
|
||||
}
|
||||
}
|
||||
field.left_ = left_;
|
||||
return field;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
for ( int j = 0; j < 3; j++ ) {
|
||||
grid_[i][j] = None;
|
||||
}
|
||||
}
|
||||
left_ = 9;
|
||||
}
|
||||
|
||||
void Show() const {
|
||||
std::cout << " 1 2 3\n";
|
||||
for ( int row = 0; row < 3; row++ ) {
|
||||
std::cout << row + 1 << " ";
|
||||
|
||||
for ( int col = 0; col < 3; col++ ) {
|
||||
if ( grid_[row][col] == PlayerA ) {
|
||||
std::cout << " X ";
|
||||
} else if ( grid_[row][col] == PlayerB ) {
|
||||
std::cout << " O ";
|
||||
} else {
|
||||
std::cout << " ";
|
||||
}
|
||||
|
||||
if ( col < 2 ) {
|
||||
std::cout << "|";
|
||||
}
|
||||
}
|
||||
|
||||
if ( row < 2 ) {
|
||||
std::cout << "\n -----------\n";
|
||||
}
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
|
||||
int SameInRow( Token token, int amount ) const {
|
||||
int sum = amount * token;
|
||||
int count = 0;
|
||||
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
if ( grid_[i][0] + grid_[i][1] + grid_[i][2] == sum ) {
|
||||
count++;
|
||||
} else if ( grid_[0][i] + grid_[1][i] + grid_[2][i] == sum ) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( grid_[0][0] + grid_[1][1] + grid_[2][2] == sum ) {
|
||||
count++;
|
||||
} else if ( grid_[2][0] + grid_[1][1] + grid_[0][2] == sum ) {
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool InRange( const Move& move ) const {
|
||||
return move.row >= 0 && move.row < 3 && move.col >= 0 && move.col < 3;
|
||||
}
|
||||
|
||||
bool IsEmpty( const Move& move ) const {
|
||||
return grid_[move.row][move.col] == None;
|
||||
}
|
||||
|
||||
bool IsFull() const {
|
||||
return left_ == 0;
|
||||
}
|
||||
|
||||
void MakeMove( const Move& move, Token token ) {
|
||||
assert( InRange( move ) );
|
||||
assert( IsEmpty( move ) );
|
||||
assert( token != None );
|
||||
assert( left_ );
|
||||
|
||||
grid_[move.row][move.col] = token;
|
||||
left_--;
|
||||
}
|
||||
|
||||
void ClearMove( const Move& move ) {
|
||||
assert( InRange(move) );
|
||||
assert( !IsEmpty(move) );
|
||||
assert( left_ < 9 );
|
||||
|
||||
grid_[move.row][move.col] = None;
|
||||
left_++;
|
||||
}
|
||||
|
||||
private:
|
||||
Token** grid_;
|
||||
int left_;
|
||||
};
|
||||
|
||||
#endif // _FIELD_
|
||||
@@ -0,0 +1,50 @@
|
||||
#ifndef _HUMAN_
|
||||
#define _HUMAN_
|
||||
|
||||
#include "input.h"
|
||||
#include "player.h"
|
||||
|
||||
class HumanPlayer : public Player {
|
||||
public:
|
||||
HumanPlayer( Field::Token token, const std::string& name )
|
||||
: Player( token, name ) {
|
||||
}
|
||||
|
||||
virtual Field::Move Turn( const Field& field ) const {
|
||||
Field::Move move;
|
||||
std::cout << name_ << '\n';
|
||||
do {
|
||||
move = Input();
|
||||
move.row -= 1;
|
||||
move.col -= 1;
|
||||
} while ( !Check( field, move ) );
|
||||
return move;
|
||||
}
|
||||
|
||||
private:
|
||||
Field::Move Input() const {
|
||||
Field::Move move;
|
||||
|
||||
std::cout << "Insert row: ";
|
||||
input::number( &move.row );
|
||||
|
||||
std::cout << "Insert column: ";
|
||||
input::number( &move.col );
|
||||
|
||||
std::cout << '\n';
|
||||
return move;
|
||||
}
|
||||
|
||||
bool Check( const Field& field, const Field::Move& move ) const {
|
||||
if ( !field.InRange( move ) ) {
|
||||
std::cout << "Wrong input!\n";
|
||||
return false;
|
||||
} else if ( !field.IsEmpty( move ) ) {
|
||||
std::cout << "Is occupied!\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _HUMAN_
|
||||
@@ -0,0 +1,20 @@
|
||||
#ifndef _INPUT_
|
||||
#define _INPUT_
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
namespace input {
|
||||
|
||||
template<typename T>
|
||||
bool number( T* number ) {
|
||||
std::string input;
|
||||
getline( std::cin, input );
|
||||
std::stringstream stream( input );
|
||||
return stream >> *number;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // _INPUT_
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "tictactoe.h"
|
||||
|
||||
int main() {
|
||||
TicTacToe tictactoe;
|
||||
|
||||
while ( tictactoe.Start() ) {
|
||||
tictactoe.Run();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#ifndef _PLAYER_
|
||||
#define _PLAYER_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "field.h"
|
||||
|
||||
class Player {
|
||||
public:
|
||||
Player( Field::Token token, const std::string& name )
|
||||
: token_( token )
|
||||
, name_( name ) {
|
||||
}
|
||||
|
||||
virtual Field::Move Turn( const Field& field ) const = 0;
|
||||
|
||||
const Field::Token token_;
|
||||
const std::string name_;
|
||||
};
|
||||
|
||||
#endif // _PLAYER_
|
||||
@@ -0,0 +1,33 @@
|
||||
class Player {
|
||||
public:
|
||||
void Do() {}
|
||||
};
|
||||
|
||||
class Base {};
|
||||
|
||||
class Game : public Base {
|
||||
public:
|
||||
Game() {
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init() {}
|
||||
|
||||
void Run() {
|
||||
player.Do();
|
||||
}
|
||||
|
||||
private:
|
||||
Player player;
|
||||
};
|
||||
|
||||
Game* game;
|
||||
|
||||
int main() {
|
||||
game = new Game();
|
||||
|
||||
game->Run();
|
||||
|
||||
delete game;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
#ifndef _TIC_TAC_TOE_
|
||||
#define _TIC_TAC_TOE_
|
||||
|
||||
#include "computer.h"
|
||||
#include "field.h"
|
||||
#include "human.h"
|
||||
#include "input.h"
|
||||
#include "player.h"
|
||||
|
||||
class TicTacToe {
|
||||
public:
|
||||
TicTacToe() {
|
||||
players_[0] = NULL;
|
||||
players_[1] = NULL;
|
||||
}
|
||||
|
||||
~TicTacToe() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool Start() {
|
||||
Reset();
|
||||
std::cout << "Tic Tac Toe\n\n[1] Human\n[2] Computer\n[3] Quit\n\n";
|
||||
|
||||
players_[0] = SelectPlayer( Field::PlayerA, "PlayerA" );
|
||||
if ( !players_[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
players_[1] = SelectPlayer( Field::PlayerB, "PlayerB" );
|
||||
if ( !players_[1] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << '\n';
|
||||
return true;
|
||||
}
|
||||
|
||||
void Run() {
|
||||
field_.Show();
|
||||
|
||||
int playerIndex = 0;
|
||||
|
||||
for ( int i = 0; i < 9; i++ ) {
|
||||
Player& player = *players_[playerIndex];
|
||||
|
||||
field_.MakeMove( player.Turn( field_ ), player.token_ );
|
||||
field_.Show();
|
||||
|
||||
if ( field_.SameInRow( player.token_, 3 ) ) {
|
||||
std::cout << player.name_ << " won!\n\n";
|
||||
return;
|
||||
}
|
||||
|
||||
playerIndex = ( playerIndex + 1 ) % 2;
|
||||
}
|
||||
|
||||
std::cout << "Game ends in draw!\n\n";
|
||||
}
|
||||
|
||||
private:
|
||||
void Reset() {
|
||||
field_.Clear();
|
||||
|
||||
for ( int i = 0; i < 2; i++ ) {
|
||||
if ( players_[i] ) {
|
||||
delete players_[i];
|
||||
players_[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player* SelectPlayer( Field::Token token, const std::string& name ) const {
|
||||
int selection;
|
||||
|
||||
while ( true ) {
|
||||
std::cout << "Choose " << name << ": ";
|
||||
input::number( &selection );
|
||||
|
||||
switch ( selection ) {
|
||||
case 1 : return new HumanPlayer( token, name );
|
||||
case 2 : return new ArtificialPlayer( token, name );
|
||||
case 3 : return NULL;
|
||||
default : std::cout << "Wrong input!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player* players_[2];
|
||||
Field field_;
|
||||
};
|
||||
|
||||
#endif // _TIC_TAC_TOE_
|
||||
@@ -0,0 +1,121 @@
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
font-family: "Consolas", monospace;
|
||||
}
|
||||
|
||||
#paper {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#files {
|
||||
padding-top: 100px;
|
||||
}
|
||||
|
||||
#files > * {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#wrapper {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
width: 450px;
|
||||
/* width: 0;*/
|
||||
height: 100%;
|
||||
overflow: scroll;
|
||||
border-left: 2px solid gray;
|
||||
background: white;
|
||||
}
|
||||
|
||||
#header {
|
||||
position: fixed;
|
||||
z-index: 100;
|
||||
background: white;
|
||||
padding-bottom: 5px;
|
||||
margin-right: 15px;
|
||||
}
|
||||
|
||||
#header .button {
|
||||
float: left;
|
||||
margin: 5px 0 0 5px;
|
||||
}
|
||||
|
||||
#top {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
padding: 10px 0;
|
||||
border-right: 2px solid gray;
|
||||
border-bottom: 2px solid gray;
|
||||
border-bottom-right-radius: 10px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
#top .button {
|
||||
display: inline-block;
|
||||
background: white;
|
||||
margin: 0 10px 0;
|
||||
line-height: 20px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
#top .button.inactive {
|
||||
color: #acacac;
|
||||
border-color: #ccc;
|
||||
}
|
||||
|
||||
#top > * {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.gap {
|
||||
clear: both;
|
||||
height: 10px;
|
||||
}
|
||||
|
||||
.button {
|
||||
border: 2px solid gray;
|
||||
color: gray;
|
||||
border-radius: 8px;
|
||||
font-size: 16px;
|
||||
line-height: 18px;
|
||||
padding: 4px 10px;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
border-color: black;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.button.selected {
|
||||
border-color: #48A65B;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.syntaxhighlighter {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter .code .line:hover {
|
||||
background-color: #EEE !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter .code .line.highlighted {
|
||||
background-color: #8FFFA5 !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter .gutter .line {
|
||||
border-color: #888 !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter .gutter .line.highlighted {
|
||||
background-color: #DDD !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
.typeahead,
|
||||
.tt-query,
|
||||
.tt-hint {
|
||||
width: 296px;
|
||||
height: 20px;
|
||||
padding: 4px 10px;
|
||||
font-size: 16px;
|
||||
line-height: 18px;
|
||||
border: 2px solid #ccc;
|
||||
-webkit-border-radius: 8px;
|
||||
-moz-border-radius: 8px;
|
||||
border-radius: 8px;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.typeahead {
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.typeahead:focus {
|
||||
border: 2px solid #0097cf;
|
||||
}
|
||||
|
||||
.tt-query {
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
|
||||
.tt-hint {
|
||||
color: #999
|
||||
}
|
||||
|
||||
.tt-dropdown-menu {
|
||||
width: 318px;
|
||||
margin-top: 6px;
|
||||
padding: 8px 0;
|
||||
background-color: #fff;
|
||||
border: 1px solid #ccc;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
-webkit-border-radius: 8px;
|
||||
-moz-border-radius: 8px;
|
||||
border-radius: 8px;
|
||||
-webkit-box-shadow: 0 5px 10px rgba(0,0,0,.2);
|
||||
-moz-box-shadow: 0 5px 10px rgba(0,0,0,.2);
|
||||
box-shadow: 0 5px 10px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
.tt-header {
|
||||
padding: 3px 20px;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-weight: bold;
|
||||
color: gray;
|
||||
margin: 10px 0 0;
|
||||
}
|
||||
|
||||
.tt-suggestion {
|
||||
padding: 3px 20px;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.tt-suggestion.tt-is-under-cursor {
|
||||
color: #fff;
|
||||
background-color: #0097cf;
|
||||
}
|
||||
|
||||
.tt-suggestion p {
|
||||
margin: 0;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
data.push( { type : 'file', name : 'artificial_player.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 6, type : 'class', name : 'ArtificialPlayer', base : 'Player', content : {
|
||||
public : [
|
||||
{ line : 8, type : 'method', return : 'ArtificialPlayer', name : 'ArtificialPlayer', params : [ 'Field::Token', 'std::string' ], content : [
|
||||
{ line : 9, type : 'call', class : 'Player', method : 'Player' }
|
||||
]},
|
||||
|
||||
{ line : 12, type : 'method', name : 'Turn', abstraction : 'virtual', return : 'Field::Move', params : [ 'Field' ], content : [
|
||||
{ line : 13, type : 'call', function : 'srand' }, { line : 13, type : 'call', function : 'time' },
|
||||
{ line : 14, type : 'call', class : 'Field', method : 'Clone' },
|
||||
{ line : 15, type : 'use', class : 'ArtificialPlayer::Node' }, { line : 15, type : 'call', method : 'MinMax' }, { line : 15, type : 'use', member : 'token_' },
|
||||
{ line : 16, type : 'use', class : 'ArtificialPlayer::Node', member : 'move' }
|
||||
]},
|
||||
|
||||
], private : [
|
||||
{ line : 20, type : 'class', name : 'Node', content : { public : [
|
||||
{ line : 21, type : 'member', name : 'move', class : 'Field::Move' },
|
||||
{ line : 22, type : 'member', name : 'value', class : 'int' }
|
||||
]}
|
||||
},
|
||||
{ line : 25, type : 'method', name : 'MinMax', return : 'Node', params : [ 'Field', 'Field::Token' ], content : [
|
||||
{ line : 26, type : 'use', class : 'Node' },
|
||||
|
||||
|
||||
{ line : 29, type : 'use', class : 'Move' },
|
||||
|
||||
|
||||
|
||||
{ line : 33, type : 'use', class : 'Move', member : 'row' },
|
||||
|
||||
|
||||
{ line : 36, type : 'use', class : 'Move', member : 'col' },
|
||||
|
||||
{ line : 38, type : 'call', class : 'Field', method : 'IsEmpty' },
|
||||
|
||||
|
||||
|
||||
{ line : 42, type : 'call', class : 'Field', method : 'MakeMove' },
|
||||
|
||||
{ line : 44, type : 'call', method : 'Evaluate' },
|
||||
{ line : 45, type : 'call', class : 'Field', method : 'IsFull' },
|
||||
{ line : 46, type : 'call', method : 'MinMax' }, { line : 46, type : 'call', class : 'Field', method : 'Opponent' }, { line : 46, type : 'use', class : 'Node', member : 'value' },
|
||||
|
||||
|
||||
{ line : 49, type : 'call', class : 'Field', method : 'ClearMove' },
|
||||
|
||||
{ line : 51, type : 'use', class : 'Node', member : 'value' },
|
||||
{ line : 52, type : 'use', class : 'Node', member : 'move' },
|
||||
{ line : 53, type : 'use', class : 'Node', member : 'value' },
|
||||
{ line : 54, type : 'use', class : 'Node', member : 'value' },
|
||||
|
||||
|
||||
{ line : 57, type : 'call', function : 'rand' },
|
||||
{ line : 58, type : 'use', class : 'Node', member : 'move' },
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
]},
|
||||
|
||||
{ line : 67, type : 'method', name : 'Evaluate', return : 'int', params : [ 'Field', 'Field::Token' ], content : [
|
||||
{ line : 68, type : 'call', class : 'Field', method : 'SameInRow' },
|
||||
|
||||
{ line : 70, type : 'call', class : 'Field', method : 'SameInRow' }, { line : 70, type : 'call', class : 'Field', method : 'Opponent' },
|
||||
|
||||
{ line : 72, type : 'call', class : 'Field', method : 'SameInRow' }
|
||||
|
||||
|
||||
|
||||
]}
|
||||
]}
|
||||
}
|
||||
]});
|
||||
@@ -0,0 +1,147 @@
|
||||
data.push( { type : 'file', name : 'field.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 7, type : 'class', name : 'Field', content : {
|
||||
public : [
|
||||
{ line : 9, type : 'class', name : 'Token', content : { public : [
|
||||
{ line : 10, type : 'member', name : 'None' },
|
||||
{ line : 11, type : 'member', name : 'PlayerA' },
|
||||
{ line : 12, type : 'member', name : 'PlayerB' }
|
||||
]}},
|
||||
|
||||
{ line : 15, type : 'method', name : 'Opponent', abstraction : 'static', return : 'Token', params : [ 'Token' ], content : [
|
||||
{ line : 16, type : 'call', function : 'assert' }, { line : 16, type : 'use', class : 'Token', member : 'None' },
|
||||
{ line : 17, type : 'use', class : 'Token', member : 'PlayerA' },
|
||||
{ line : 18, type : 'use', class : 'Token', member : 'PlayerB' },
|
||||
|
||||
{ line : 20, type : 'use', class : 'Token', member : 'PlayerA' }
|
||||
|
||||
]},
|
||||
|
||||
{ line : 24, type : 'class', name : 'Move', content : { public : [
|
||||
{ line : 25, type : 'member', name : 'row', class : 'int' },
|
||||
{ line : 26, type : 'member', name : 'col', class : 'int' }
|
||||
]}},
|
||||
|
||||
{ line : 29, type : 'method', return : 'Field', name : 'Field', content : [
|
||||
{ line : 30, type : 'use', member : 'left_' },
|
||||
{ line : 31, type : 'use', member : 'grid_' }, { line : 31, type : 'use', class : 'Token' },
|
||||
|
||||
{ line : 33, type : 'use', member : 'grid_' }, { line : 33, type : 'use', class : 'Token' },
|
||||
|
||||
]},
|
||||
|
||||
{ line : 37, type : 'method', name : '~Field', content : [
|
||||
|
||||
{ line : 39, type : 'use', member : 'grid_' },
|
||||
|
||||
{ line : 41, type : 'use', member : 'grid_' },
|
||||
]},
|
||||
|
||||
{ line : 44, type : 'method', name : 'Clone', return : 'Field', content : [
|
||||
|
||||
|
||||
|
||||
{ line : 48, type : 'use', member : 'grid_' }, { line : 48, type : 'use', member : 'grid_' },
|
||||
|
||||
|
||||
{ line : 51, type : 'use', member : 'left_' }, { line : 51, type : 'use', member : 'left_' }
|
||||
]},
|
||||
|
||||
|
||||
{ line : 55, type : 'method', name : 'Clear', return : 'void', content : [
|
||||
|
||||
|
||||
{ line : 58, type : 'use', member : 'grid_' }, { line : 58, type : 'use', class : 'Token', member : 'None' },
|
||||
|
||||
|
||||
{ line : 61, type : 'use', member : 'left_' }
|
||||
]},
|
||||
|
||||
{ line : 64, type : 'method', name : 'Show', return : 'void', content : [
|
||||
{ line : 65, type : 'use', class : 'std::cout' },
|
||||
|
||||
{ line : 67, type : 'use', class : 'std::cout' },
|
||||
|
||||
|
||||
{ line : 70, type : 'use', member : 'grid_' }, { line : 70, type : 'use', class : 'Token', member : 'PlayerA' },
|
||||
{ line : 71, type : 'use', class : 'std::cout' },
|
||||
{ line : 72, type : 'use', member : 'grid_' }, { line : 71, type : 'use', class : 'Token', member : 'PlayerA' },
|
||||
{ line : 73, type : 'use', class : 'std::cout' },
|
||||
|
||||
{ line : 75, type : 'use', class : 'std::cout' },
|
||||
|
||||
|
||||
|
||||
{ line : 79, type : 'use', class : 'std::cout' },
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 84, type : 'use', class : 'std::cout' },
|
||||
|
||||
|
||||
{ line : 87, type : 'use', class : 'std::cout' }
|
||||
]},
|
||||
|
||||
{ line : 90, type : 'method', name : 'SameInRow', return : 'int', params : [ 'Token', 'int' ], content : [
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 95, type : 'use', member : 'grid_' }, { line : 95, type : 'use', member : 'grid_' }, { line : 95, type : 'use', member : 'grid_' },
|
||||
|
||||
{ line : 97, type : 'use', member : 'grid_' }, { line : 97, type : 'use', member : 'grid_' }, { line : 97, type : 'use', member : 'grid_' },
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 102, type : 'use', member : 'grid_' }, { line : 102, type : 'use', member : 'grid_' }, { line : 102, type : 'use', member : 'grid_' },
|
||||
|
||||
{ line : 104, type : 'use', member : 'grid_' }, { line : 104, type : 'use', member : 'grid_' }, { line : 104, type : 'use', member : 'grid_' },
|
||||
|
||||
|
||||
|
||||
|
||||
]},
|
||||
|
||||
{ line : 111, type : 'method', name : 'InRange', return : 'bool', params : [ 'Move' ], content : [
|
||||
{ line : 112, type : 'use', class : 'Move', member : 'row' }, { line : 112, type : 'use', class : 'Move', member : 'row' }, { line : 112, type : 'use', class : 'Move', member : 'col' }, { line : 112, type : 'use', class : 'Move', member : 'col' }
|
||||
]},
|
||||
|
||||
{ line : 115, type : 'method', name : 'IsEmpty', return : 'bool', params : [ 'Move' ], content : [
|
||||
{ line : 116, type : 'use', member : 'grid_' }, { line : 116, type : 'use', class : 'Move', member : 'row' }, { line : 116, type : 'use', class : 'Move', member : 'col' }, { line : 116, type : 'use', class : 'Token', member : 'None' }
|
||||
]},
|
||||
|
||||
{ line : 119, type : 'method', name : 'IsFull', return : 'bool', content : [
|
||||
{ line : 120, type : 'use', member : 'left_' }
|
||||
]},
|
||||
|
||||
{ line : 123, type : 'method', name : 'MakeMove', return : 'void', params : [ 'Move', 'Token' ], content : [
|
||||
{ line : 124, type : 'call', function : 'assert' }, { line : 124, type : 'call', method : 'InRange' },
|
||||
{ line : 125, type : 'call', function : 'assert' }, { line : 125, type : 'call', method : 'IsEmpty' },
|
||||
{ line : 126, type : 'call', function : 'assert' }, { line : 126, type : 'use', class : 'Token', member : 'None' },
|
||||
{ line : 127, type : 'call', function : 'assert' }, { line : 127, type : 'use', member : 'left_' },
|
||||
|
||||
{ line : 129, type : 'use', member : 'grid_' }, { line : 129, type : 'use', class : 'Move', member : 'row' }, { line : 129, type : 'use', class : 'Move', member : 'col' },
|
||||
{ line : 130, type : 'use', member : 'left_' },
|
||||
]},
|
||||
|
||||
{ line : 133, type : 'method', name : 'ClearMove', return : 'void', params : [ 'Move' ], content : [
|
||||
{ line : 134, type : 'call', function : 'assert' }, { line : 134, type : 'call', method : 'InRange' },
|
||||
{ line : 135, type : 'call', function : 'assert' }, { line : 135, type : 'call', method : 'IsEmpty' },
|
||||
{ line : 136, type : 'call', function : 'assert' }, { line : 136, type : 'use', member : 'left_' },
|
||||
|
||||
{ line : 138, type : 'use', member : 'grid_' }, { line : 138, type : 'use', class : 'Move', member : 'row' }, { line : 138, type : 'use', class : 'Move', member : 'col' }, { line : 138, type : 'use', class : 'Token', member : 'None' },
|
||||
{ line : 139, type : 'use', member : 'left_' },
|
||||
]}
|
||||
|
||||
], private : [
|
||||
{ line : 143, type : 'member', name : 'grid_', class : 'Token' },
|
||||
{ line : 144, type : 'member', name : 'left_', class : 'int' }
|
||||
]}
|
||||
}
|
||||
]});
|
||||
@@ -0,0 +1,50 @@
|
||||
data.push( { type : 'file', name : 'human_player.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 7, type : 'class', name : 'HumanPlayer', base : 'Player', content : {
|
||||
public : [
|
||||
{ line : 9, type : 'method', name : 'HumanPlayer', return : 'HumanPlayer', params : [ 'Field::Token', 'std::string' ], content : [
|
||||
{ line : 10, type : 'call', class : 'Player', method : 'Player' }
|
||||
]},
|
||||
|
||||
{ line : 13, type : 'method', name : 'Turn', abstraction : 'virtual', return : 'Field::Move', params : [ 'Field' ], content : [
|
||||
|
||||
{ line : 15, type : 'use', class : 'std::cout' },
|
||||
|
||||
{ line : 17, type : 'call', method : 'Input' },
|
||||
{ line : 18, type : 'use', class : 'Move', member : 'row' },
|
||||
{ line : 19, type : 'use', class : 'Move', member : 'col' },
|
||||
{ line : 20, type : 'call', method : 'Check' }
|
||||
|
||||
]},
|
||||
|
||||
], private : [
|
||||
{ line : 25, type : 'method', name : 'Input', return : 'Field::Move', content : [
|
||||
{ line : 26, type : 'use', class : 'Move' },
|
||||
|
||||
{ line : 28, type : 'use', class : 'std::cout' },
|
||||
{ line : 29, type : 'call', function : 'input::number' }, { line : 29, type : 'use', class : 'Move', member : 'row' },
|
||||
|
||||
{ line : 31, type : 'use', class : 'std::cout' },
|
||||
{ line : 32, type : 'call', function : 'input::number' }, { line : 32, type : 'use', class : 'Move', member : 'col' },
|
||||
|
||||
{ line : 34, type : 'use', class : 'std::cout' }
|
||||
|
||||
]},
|
||||
|
||||
{ line : 38, type : 'method', name : 'Check', return : 'bool', params : [ 'Field', 'Field::Move' ], content : [
|
||||
{ line : 39, type : 'call', class : 'Field', method : 'InRange' },
|
||||
{ line : 40, type : 'use', class : 'std::cout' },
|
||||
|
||||
{ line : 42, type : 'call', class : 'Field', method : 'IsEmpty' },
|
||||
{ line : 43, type : 'use', class : 'std::cout' }
|
||||
|
||||
|
||||
|
||||
]}
|
||||
]}
|
||||
}
|
||||
]});
|
||||
@@ -0,0 +1,20 @@
|
||||
data.push( { type : 'file', name : 'input.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 11, type : 'function', name : 'input::number', return : 'bool', content : [
|
||||
{ line : 12, type : 'use', class : 'std::string'},
|
||||
{ line : 13, type : 'call', function : 'getline'}, { line : 13, type : 'use', class : 'std::cin'},
|
||||
{ line : 14, type : 'use', class : 'std::stringstream'}
|
||||
|
||||
]}
|
||||
|
||||
|
||||
|
||||
]});
|
||||
@@ -0,0 +1,11 @@
|
||||
data.push( { type : 'file', name : 'main.cpp', content : [
|
||||
|
||||
{ line : 3, type : 'function', name : 'main', return : 'int', content : [
|
||||
{ line : 4, type : 'call', class : 'TicTacToe', method : 'TicTacToe' },
|
||||
|
||||
{ line : 6, type : 'call', class : 'TicTacToe', method : 'Start' },
|
||||
{ line : 7, type : 'call', class : 'TicTacToe', method : 'Run' }
|
||||
|
||||
|
||||
]}
|
||||
]});
|
||||
@@ -0,0 +1,21 @@
|
||||
data.push( { type : 'file', name : 'player.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 8, type : 'class', name : 'Player', content : {
|
||||
public : [
|
||||
{ line : 10, type : 'method', name : 'Player', return : 'Player', params : [ 'Field::Token', 'std::string' ], content : [
|
||||
{ line : 11, type : 'use', member : 'token_' },
|
||||
{ line : 12, type : 'use', member : 'name_' }
|
||||
]},
|
||||
|
||||
{ line : 15, type : 'method', name : 'Turn', abstraction : 'pure_virtual', return : 'Field::Move', params : [ 'Field' ] },
|
||||
|
||||
{ line : 17, type : 'member', name : 'token_', class : 'Field::Token' },
|
||||
{ line : 18, type : 'member', name : 'name_', class : 'std::string' },
|
||||
]}
|
||||
}
|
||||
]});
|
||||
@@ -0,0 +1,34 @@
|
||||
data.push( { type : 'file', name : 'sample.cpp', content : [
|
||||
{ line : 1, type : 'class', name : 'Player', content : {
|
||||
public : [
|
||||
{ line : 3, type : 'method', name : 'Do', return : 'void' }
|
||||
]
|
||||
}},
|
||||
{ line : 6, type : 'class', name : 'Base' },
|
||||
|
||||
{ line : 8, type : 'class', name : 'Game', base : 'Base', content : {
|
||||
public : [
|
||||
{ line : 10, type : 'method', name : 'Game', content : [
|
||||
{ line : 11, type : 'call', method : 'Init' }
|
||||
]},
|
||||
|
||||
{ line : 14, type : 'method', name : 'Init' },
|
||||
|
||||
{ line : 16, type : 'method', name : 'Run', content : [
|
||||
{ line : 17, type : 'use', member : 'player' }, { line : 17, type : 'call', method : 'Do', class : 'Player' }
|
||||
]}
|
||||
],
|
||||
private : [
|
||||
{ line : 21, type : 'member', name : 'player', class : 'Player' }
|
||||
]
|
||||
}},
|
||||
{ line : 24, type : 'variable', name : 'game', class : 'Game' },
|
||||
|
||||
{ line : 26, type : 'function', name : 'main', return : 'int', content : [
|
||||
{ line : 27, type : 'use', variable : 'game' }, { line : 27, type : 'call', method : 'Game', class : 'Game' },
|
||||
|
||||
{ line : 29, type : 'use', variable : 'game' }, { line : 29, type : 'call', method : 'Run', class : 'Game' },
|
||||
|
||||
{ line : 31, type : 'use', variable : 'game' }
|
||||
]}
|
||||
]});
|
||||
@@ -0,0 +1,93 @@
|
||||
data.push( { type : 'file', name : 'tictactoe.h', content : [
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 10, type : 'class', name : 'TicTacToe', content : {
|
||||
public : [
|
||||
{ line : 12, type : 'method', name : 'TicTacToe', return : 'TicTacToe', content : [
|
||||
{ line : 13, type : 'use', member : 'players_' },
|
||||
{ line : 14, type : 'use', member : 'players_' }
|
||||
]},
|
||||
|
||||
{ line : 17, type : 'method', name : '~TicTacToe', content : [
|
||||
{ line : 18, type : 'call', method : 'Reset' }
|
||||
]},
|
||||
|
||||
{ line : 21, type : 'method', name : 'Start', return : 'bool', content : [
|
||||
{ line : 22, type : 'call', method : 'Reset' },
|
||||
{ line : 23, type : 'use', class : 'std::cout' },
|
||||
|
||||
{ line : 25, type : 'use', member : 'players_' }, { line : 25, type : 'call', method : 'SelectPlayer' }, { line : 25, type : 'use', class : 'Field::Token', member : 'PlayerA' },
|
||||
{ line : 26, type : 'use', member : 'players_' },
|
||||
|
||||
|
||||
|
||||
{ line : 30, type : 'use', member : 'players_' }, { line : 30, type : 'call', method : 'SelectPlayer' }, { line : 30, type : 'use', class : 'Field::Token', member : 'PlayerB' },
|
||||
{ line : 31, type : 'use', member : 'players_' },
|
||||
|
||||
|
||||
|
||||
{ line : 35, type : 'use', class : 'std::cout' },
|
||||
|
||||
]},
|
||||
|
||||
{ line : 39, type : 'method', name : 'Run', return : 'void', content : [
|
||||
{ line : 40, type : 'use', member : 'field_' }, { line : 40, type : 'call', method : 'Show', class : 'Field' },
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 45, type : 'use', member : 'players_' },
|
||||
|
||||
{ line : 47, type : 'use', member : 'field_' }, { line : 47, type : 'call', method : 'MakeMove', class : 'Field' }, { line : 47, type : 'call', method : 'Turn', class : 'Player' }, { line : 47, type : 'use', member : 'token_', class : 'Player' },
|
||||
{ line : 48, type : 'use', member : 'field_' }, { line : 48, type : 'call', method : 'Show', class : 'Field' },
|
||||
|
||||
{ line : 50, type : 'use', member : 'field_' }, { line : 50, type : 'call', method : 'SameInRow', class : 'Field' }, { line : 50, type : 'use', member : 'token_', class : 'Player' },
|
||||
{ line : 51, type : 'use', class : 'std::cout' }, { line : 51, type : 'use', member : 'name_', class : 'Player' },
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
{ line : 58, type : 'use', class : 'std::cout' }
|
||||
]},
|
||||
|
||||
], private : [
|
||||
{ line : 62, type : 'method', name : 'Reset', return : 'void', content : [
|
||||
{ line : 63, type : 'use', member : 'field_' }, { line : 63, type : 'call', method : 'Clear', class : 'Field' },
|
||||
|
||||
|
||||
{ line : 66, type : 'use', member : 'players_' },
|
||||
{ line : 67, type : 'use', member : 'players_' },
|
||||
{ line : 68, type : 'use', member : 'players_' }
|
||||
|
||||
|
||||
]},
|
||||
|
||||
{ line : 73, type : 'method', name : 'SelectPlayer', return : 'Player', params : [ 'Field::Token', 'std::string' ], content : [
|
||||
|
||||
|
||||
|
||||
{ line : 77, type : 'use', class : 'std::cout' },
|
||||
{ line : 78, type : 'call', function : 'input::number' },
|
||||
|
||||
|
||||
{ line : 81, type : 'call', method : 'HumanPlayer', class : 'HumanPlayer' },
|
||||
{ line : 82, type : 'call', method : 'ArtificialPlayer', class : 'ArtificialPlayer' },
|
||||
|
||||
{ line : 84, type : 'use', class : 'std::cout' }
|
||||
|
||||
|
||||
]},
|
||||
|
||||
{ line : 89, type : 'member', name : 'players_', class : 'Player' },
|
||||
{ line : 90, type : 'member', name : 'field_', class : 'Field' }
|
||||
]}
|
||||
}
|
||||
]});
|
||||
@@ -0,0 +1,567 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
|
||||
<title>Concept Prototype</title>
|
||||
|
||||
<meta name="robots" content="noindex" />
|
||||
|
||||
<link type="text/css" rel="stylesheet" href="lib/syntaxhighlighter/styles/shCoreDefault.css"/>
|
||||
<link type="text/css" rel="stylesheet" href="css/typeahead.css" />
|
||||
<link type="text/css" rel="stylesheet" href="css/style.css" />
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="paper"></div>
|
||||
|
||||
<div id="top">
|
||||
<input type="button" class="button" id="back" value="◀" />
|
||||
<input class="typeahead search" type="text" placeholder="Search Code">
|
||||
<input type="button" class="button" id="all" value="all" />
|
||||
</div>
|
||||
|
||||
<div id="wrapper">
|
||||
<div id="header"></div>
|
||||
|
||||
<div class="gap"></div>
|
||||
|
||||
<div id="files">
|
||||
<div id="main">
|
||||
<pre class="brush:cpp">
|
||||
#include "tictactoe.h"
|
||||
|
||||
int main() {
|
||||
TicTacToe tictactoe;
|
||||
|
||||
while ( tictactoe.Start() ) {
|
||||
tictactoe.Run();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
<div id="tictactoe">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _TIC_TAC_TOE_
|
||||
#define _TIC_TAC_TOE_
|
||||
|
||||
#include "artificial_player.h"
|
||||
#include "field.h"
|
||||
#include "human_player.h"
|
||||
#include "input.h"
|
||||
#include "player.h"
|
||||
|
||||
class TicTacToe {
|
||||
public:
|
||||
TicTacToe() {
|
||||
players_[0] = NULL;
|
||||
players_[1] = NULL;
|
||||
}
|
||||
|
||||
~TicTacToe() {
|
||||
Reset();
|
||||
}
|
||||
|
||||
bool Start() {
|
||||
Reset();
|
||||
std::cout << "Tic Tac Toe\n\n[1] Human\n[2] Computer\n[3] Quit\n\n";
|
||||
|
||||
players_[0] = SelectPlayer( Field::PlayerA, "PlayerA" );
|
||||
if ( !players_[0] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
players_[1] = SelectPlayer( Field::PlayerB, "PlayerB" );
|
||||
if ( !players_[1] ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << '\n';
|
||||
return true;
|
||||
}
|
||||
|
||||
void Run() {
|
||||
field_.Show();
|
||||
|
||||
int playerIndex = 0;
|
||||
|
||||
for ( int i = 0; i < 9; i++ ) {
|
||||
Player& player = *players_[playerIndex];
|
||||
|
||||
field_.MakeMove( player.Turn( field_ ), player.token_ );
|
||||
field_.Show();
|
||||
|
||||
if ( field_.SameInRow( player.token_, 3 ) ) {
|
||||
std::cout << player.name_ << " won!\n\n";
|
||||
return;
|
||||
}
|
||||
|
||||
playerIndex = ( playerIndex + 1 ) % 2;
|
||||
}
|
||||
|
||||
std::cout << "Game ends in draw!\n\n";
|
||||
}
|
||||
|
||||
private:
|
||||
void Reset() {
|
||||
field_.Clear();
|
||||
|
||||
for ( int i = 0; i < 2; i++ ) {
|
||||
if ( players_[i] ) {
|
||||
delete players_[i];
|
||||
players_[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player* SelectPlayer( Field::Token token, const std::string& name ) const {
|
||||
int selection;
|
||||
|
||||
while ( true ) {
|
||||
std::cout << "Choose " << name << ": ";
|
||||
input::number( &selection );
|
||||
|
||||
switch ( selection ) {
|
||||
case 1 : return new HumanPlayer( token, name );
|
||||
case 2 : return new ArtificialPlayer( token, name );
|
||||
case 3 : return NULL;
|
||||
default : std::cout << "Wrong input!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Player* players_[2];
|
||||
Field field_;
|
||||
};
|
||||
|
||||
#endif // _TIC_TAC_TOE_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="field">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _FIELD_
|
||||
#define _FIELD_
|
||||
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
class Field {
|
||||
public:
|
||||
enum Token {
|
||||
None = 0,
|
||||
PlayerA = 1,
|
||||
PlayerB = 4
|
||||
};
|
||||
|
||||
static Token Opponent( Token token ) {
|
||||
assert( token != None );
|
||||
if ( token == PlayerA ) {
|
||||
return PlayerB;
|
||||
} else {
|
||||
return PlayerA;
|
||||
}
|
||||
}
|
||||
|
||||
struct Move {
|
||||
int row;
|
||||
int col;
|
||||
};
|
||||
|
||||
Field()
|
||||
: left_( 9 ) {
|
||||
grid_ = new Token* [3];
|
||||
for ( int i = 0; i < 3 ; i++ ) {
|
||||
grid_[i] = new Token[3];
|
||||
}
|
||||
}
|
||||
|
||||
~Field() {
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
delete grid_[i];
|
||||
}
|
||||
delete [] grid_;
|
||||
}
|
||||
|
||||
Field Clone() const {
|
||||
Field field;
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
for ( int j = 0; j < 3; j++ ) {
|
||||
field.grid_[i][j] = grid_[i][j];
|
||||
}
|
||||
}
|
||||
field.left_ = left_;
|
||||
return field;
|
||||
}
|
||||
|
||||
void Clear() {
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
for ( int j = 0; j < 3; j++ ) {
|
||||
grid_[i][j] = None;
|
||||
}
|
||||
}
|
||||
left_ = 9;
|
||||
}
|
||||
|
||||
void Show() const {
|
||||
std::cout << " 1 2 3\n";
|
||||
for ( int row = 0; row < 3; row++ ) {
|
||||
std::cout << row + 1 << " ";
|
||||
|
||||
for ( int col = 0; col < 3; col++ ) {
|
||||
if ( grid_[row][col] == PlayerA ) {
|
||||
std::cout << " X ";
|
||||
} else if ( grid_[row][col] == PlayerB ) {
|
||||
std::cout << " O ";
|
||||
} else {
|
||||
std::cout << " ";
|
||||
}
|
||||
|
||||
if ( col < 2 ) {
|
||||
std::cout << "|";
|
||||
}
|
||||
}
|
||||
|
||||
if ( row < 2 ) {
|
||||
std::cout << "\n -----------\n";
|
||||
}
|
||||
}
|
||||
std::cout << "\n\n";
|
||||
}
|
||||
|
||||
int SameInRow( Token token, int amount ) const {
|
||||
int sum = amount * token;
|
||||
int count = 0;
|
||||
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
if ( grid_[i][0] + grid_[i][1] + grid_[i][2] == sum ) {
|
||||
count++;
|
||||
} else if ( grid_[0][i] + grid_[1][i] + grid_[2][i] == sum ) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ( grid_[0][0] + grid_[1][1] + grid_[2][2] == sum ) {
|
||||
count++;
|
||||
} else if ( grid_[2][0] + grid_[1][1] + grid_[0][2] == sum ) {
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
bool InRange( const Move& move ) const {
|
||||
return move.row >= 0 && move.row < 3 && move.col >= 0 && move.col < 3;
|
||||
}
|
||||
|
||||
bool IsEmpty( const Move& move ) const {
|
||||
return grid_[move.row][move.col] == None;
|
||||
}
|
||||
|
||||
bool IsFull() const {
|
||||
return left_ == 0;
|
||||
}
|
||||
|
||||
void MakeMove( const Move& move, Token token ) {
|
||||
assert( InRange( move ) );
|
||||
assert( IsEmpty( move ) );
|
||||
assert( token != None );
|
||||
assert( left_ );
|
||||
|
||||
grid_[move.row][move.col] = token;
|
||||
left_--;
|
||||
}
|
||||
|
||||
void ClearMove( const Move& move ) {
|
||||
assert( InRange(move) );
|
||||
assert( !IsEmpty(move) );
|
||||
assert( left_ < 9 );
|
||||
|
||||
grid_[move.row][move.col] = None;
|
||||
left_++;
|
||||
}
|
||||
|
||||
private:
|
||||
Token** grid_;
|
||||
int left_;
|
||||
};
|
||||
|
||||
#endif // _FIELD_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="player">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _PLAYER_
|
||||
#define _PLAYER_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "field.h"
|
||||
|
||||
class Player {
|
||||
public:
|
||||
Player( Field::Token token, const std::string& name )
|
||||
: token_( token )
|
||||
, name_( name ) {
|
||||
}
|
||||
|
||||
virtual Field::Move Turn( const Field& field ) const = 0;
|
||||
|
||||
const Field::Token token_;
|
||||
const std::string name_;
|
||||
};
|
||||
|
||||
#endif // _PLAYER_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="human_player">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _HUMAN_
|
||||
#define _HUMAN_
|
||||
|
||||
#include "input.h"
|
||||
#include "player.h"
|
||||
|
||||
class HumanPlayer : public Player {
|
||||
public:
|
||||
HumanPlayer( Field::Token token, const std::string& name )
|
||||
: Player( token, name ) {
|
||||
}
|
||||
|
||||
virtual Field::Move Turn( const Field& field ) const {
|
||||
Field::Move move;
|
||||
std::cout << name_ << '\n';
|
||||
do {
|
||||
move = Input();
|
||||
move.row -= 1;
|
||||
move.col -= 1;
|
||||
} while ( !Check( field, move ) );
|
||||
return move;
|
||||
}
|
||||
|
||||
private:
|
||||
Field::Move Input() const {
|
||||
Field::Move move;
|
||||
|
||||
std::cout << "Insert row: ";
|
||||
input::number( &move.row );
|
||||
|
||||
std::cout << "Insert column: ";
|
||||
input::number( &move.col );
|
||||
|
||||
std::cout << '\n';
|
||||
return move;
|
||||
}
|
||||
|
||||
bool Check( const Field& field, const Field::Move& move ) const {
|
||||
if ( !field.InRange( move ) ) {
|
||||
std::cout << "Wrong input!\n";
|
||||
return false;
|
||||
} else if ( !field.IsEmpty( move ) ) {
|
||||
std::cout << "Is occupied!\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _HUMAN_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="artificial_player">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _ARTIFICIAL_
|
||||
#define _ARTIFICIAL_
|
||||
|
||||
#include "player.h"
|
||||
|
||||
class ArtificialPlayer : public Player {
|
||||
public:
|
||||
ArtificialPlayer( Field::Token token, const std::string& name )
|
||||
: Player( token, name ) {
|
||||
}
|
||||
|
||||
virtual Field::Move Turn( const Field& field ) const {
|
||||
srand( static_cast<unsigned int>( time( NULL ) ) );
|
||||
Field fakeField = field.Clone();
|
||||
Node node = MinMax( fakeField, token_ );
|
||||
return node.move;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Node {
|
||||
Field::Move move;
|
||||
int value;
|
||||
};
|
||||
|
||||
Node MinMax( Field& field, Field::Token token ) const {
|
||||
Node node;
|
||||
node.value = -10000;
|
||||
|
||||
Field::Move move;
|
||||
int sameMove;
|
||||
|
||||
for ( int i = 0; i < 3; i++ ) {
|
||||
move.row = i;
|
||||
|
||||
for ( int j = 0; j < 3; j++ ) {
|
||||
move.col = j;
|
||||
|
||||
if ( !field.IsEmpty( move ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
field.MakeMove( move, token );
|
||||
|
||||
int turnValue = Evaluate( field, token );
|
||||
if ( !turnValue && !field.IsFull() ) {
|
||||
turnValue = -MinMax( field, Field::Opponent( token ) ).value;
|
||||
}
|
||||
|
||||
field.ClearMove( move );
|
||||
|
||||
if ( turnValue > node.value ) {
|
||||
node.move = move;
|
||||
node.value = turnValue;
|
||||
sameMove = 1;
|
||||
} else if ( turnValue == node.value ) {
|
||||
sameMove++;
|
||||
if ( rand() % sameMove == 0 ) {
|
||||
node.move = move;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
int Evaluate( const Field& field, Field::Token token ) const {
|
||||
if ( field.SameInRow( token, 3 ) ) {
|
||||
return 2;
|
||||
} else if ( field.SameInRow( Field::Opponent( token ), 2 ) ) {
|
||||
return -1;
|
||||
} else if ( field.SameInRow( token, 2 ) > 1 ) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _ARTIFICIAL_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="input">
|
||||
<pre class="brush:cpp">
|
||||
#ifndef _INPUT_
|
||||
#define _INPUT_
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace input {
|
||||
|
||||
template<typename T>
|
||||
bool number( T* number ) {
|
||||
std::string input;
|
||||
getline( std::cin, input );
|
||||
std::stringstream stream( input );
|
||||
return stream >> *number;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // _INPUT_
|
||||
</pre>
|
||||
</div>
|
||||
<div id="sample">
|
||||
<pre class="brush:cpp">
|
||||
|
||||
class Player {
|
||||
public:
|
||||
void Do() {}
|
||||
};
|
||||
|
||||
class Base {};
|
||||
|
||||
class Game : public Base {
|
||||
public:
|
||||
Game() {
|
||||
Init();
|
||||
}
|
||||
|
||||
void Init() {}
|
||||
|
||||
void Run() {
|
||||
player.Do();
|
||||
}
|
||||
|
||||
private:
|
||||
Player player;
|
||||
};
|
||||
|
||||
Game* game;
|
||||
|
||||
int main() {
|
||||
game = new Game();
|
||||
|
||||
game->Run();
|
||||
|
||||
delete game;
|
||||
return 0;
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="lib/jquery-2.0.0.min.js"></script>
|
||||
<script src="lib/jquery.scrollTo-1.4.3.1-min.js"></script>
|
||||
<script src="lib/typeahead-0.9.3.js"></script>
|
||||
<script src="lib/raphael-2.1.2.js"></script>
|
||||
|
||||
<script src="lib/syntaxhighlighter/scripts/shCore.js"></script>
|
||||
<script src="lib/syntaxhighlighter/scripts/shBrushCpp.js"></script>
|
||||
|
||||
<script src="src/utils/vector.js"></script>
|
||||
<script src="src/utils/utilities.js"></script>
|
||||
<script src="src/utils/raphael_extensions.js"></script>
|
||||
|
||||
<script src="src/kit.js"></script>
|
||||
<script src="src/location.js"></script>
|
||||
|
||||
<script src="src/model/node_model.js"></script>
|
||||
<script src="src/model/edge_model.js"></script>
|
||||
<script src="src/model/graph_model.js"></script>
|
||||
<script src="src/model/class_model.js"></script>
|
||||
<script src="src/model/program_model.js"></script>
|
||||
|
||||
<script src="src/view/animation_layout.js"></script>
|
||||
<script src="src/view/force_layout.js"></script>
|
||||
|
||||
<script src="src/view/view.js"></script>
|
||||
<script src="src/view/node_view.js"></script>
|
||||
<script src="src/view/edge_view.js"></script>
|
||||
<script src="src/view/class_view.js"></script>
|
||||
<script src="src/view/program_view.js"></script>
|
||||
|
||||
<script src="src/interpreter.js"></script>
|
||||
<script src="src/fileviewer.js"></script>
|
||||
|
||||
<script src="src/main.js"></script>
|
||||
|
||||
<script> var data = []; </script>
|
||||
<script src="data/sample.js"></script>
|
||||
<script src="data/input.js"></script>
|
||||
<script src="data/field.js"></script>
|
||||
<script src="data/player.js"></script>
|
||||
<script src="data/human_player.js"></script>
|
||||
<script src="data/artificial_player.js"></script>
|
||||
<script src="data/tictactoe.js"></script>
|
||||
<script src="data/main.js"></script>
|
||||
<script> main( data ); </script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Copyright (c) 2007-2012 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
|
||||
* Dual licensed under MIT and GPL.
|
||||
* @author Ariel Flesler
|
||||
* @version 1.4.3.1
|
||||
*/
|
||||
;(function($){var h=$.scrollTo=function(a,b,c){$(window).scrollTo(a,b,c)};h.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1,limit:true};h.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(e,f,g){if(typeof f=='object'){g=f;f=0}if(typeof g=='function')g={onAfter:g};if(e=='max')e=9e9;g=$.extend({},h.defaults,g);f=f||g.duration;g.queue=g.queue&&g.axis.length>1;if(g.queue)f/=2;g.offset=both(g.offset);g.over=both(g.over);return this._scrollable().each(function(){if(e==null)return;var d=this,$elem=$(d),targ=e,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=)?\d+(\.\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}$.each(g.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=h.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(g.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=g.offset[pos]||0;if(g.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*g.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(g.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&g.queue){if(old!=attr[key])animate(g.onAfterFirst);delete attr[key]}});animate(g.onAfter);function animate(a){$elem.animate(attr,f,g.easing,a&&function(){a.call(this,e,g)})}}).end()};h.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return typeof a=='object'?a:{top:a,left:a}}})(jQuery);
|
||||
@@ -0,0 +1,165 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser General Public License from time to time. Such new
|
||||
versions will be similar in spirit to the present version, but may
|
||||
differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2003, 2004 Jim Weirich
|
||||
|
||||
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.
|
||||
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* SyntaxHighlighter
|
||||
* http://alexgorbatchev.com/SyntaxHighlighter
|
||||
*
|
||||
* SyntaxHighlighter is donationware. If you are using it, please donate.
|
||||
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
|
||||
*
|
||||
* @version
|
||||
* 3.0.83 (July 02 2010)
|
||||
*
|
||||
* @copyright
|
||||
* Copyright (C) 2004-2010 Alex Gorbatchev.
|
||||
*
|
||||
* @license
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
*/
|
||||
;(function()
|
||||
{
|
||||
// CommonJS
|
||||
typeof(require) != 'undefined' ? SyntaxHighlighter = require('shCore').SyntaxHighlighter : null;
|
||||
|
||||
function Brush()
|
||||
{
|
||||
// Copyright 2006 Shin, YoungJin
|
||||
|
||||
var datatypes = 'ATOM BOOL BOOLEAN BYTE CHAR COLORREF DWORD DWORDLONG DWORD_PTR ' +
|
||||
'DWORD32 DWORD64 FLOAT HACCEL HALF_PTR HANDLE HBITMAP HBRUSH ' +
|
||||
'HCOLORSPACE HCONV HCONVLIST HCURSOR HDC HDDEDATA HDESK HDROP HDWP ' +
|
||||
'HENHMETAFILE HFILE HFONT HGDIOBJ HGLOBAL HHOOK HICON HINSTANCE HKEY ' +
|
||||
'HKL HLOCAL HMENU HMETAFILE HMODULE HMONITOR HPALETTE HPEN HRESULT ' +
|
||||
'HRGN HRSRC HSZ HWINSTA HWND INT INT_PTR INT32 INT64 LANGID LCID LCTYPE ' +
|
||||
'LGRPID LONG LONGLONG LONG_PTR LONG32 LONG64 LPARAM LPBOOL LPBYTE LPCOLORREF ' +
|
||||
'LPCSTR LPCTSTR LPCVOID LPCWSTR LPDWORD LPHANDLE LPINT LPLONG LPSTR LPTSTR ' +
|
||||
'LPVOID LPWORD LPWSTR LRESULT PBOOL PBOOLEAN PBYTE PCHAR PCSTR PCTSTR PCWSTR ' +
|
||||
'PDWORDLONG PDWORD_PTR PDWORD32 PDWORD64 PFLOAT PHALF_PTR PHANDLE PHKEY PINT ' +
|
||||
'PINT_PTR PINT32 PINT64 PLCID PLONG PLONGLONG PLONG_PTR PLONG32 PLONG64 POINTER_32 ' +
|
||||
'POINTER_64 PSHORT PSIZE_T PSSIZE_T PSTR PTBYTE PTCHAR PTSTR PUCHAR PUHALF_PTR ' +
|
||||
'PUINT PUINT_PTR PUINT32 PUINT64 PULONG PULONGLONG PULONG_PTR PULONG32 PULONG64 ' +
|
||||
'PUSHORT PVOID PWCHAR PWORD PWSTR SC_HANDLE SC_LOCK SERVICE_STATUS_HANDLE SHORT ' +
|
||||
'SIZE_T SSIZE_T TBYTE TCHAR UCHAR UHALF_PTR UINT UINT_PTR UINT32 UINT64 ULONG ' +
|
||||
'ULONGLONG ULONG_PTR ULONG32 ULONG64 USHORT USN VOID WCHAR WORD WPARAM WPARAM WPARAM ' +
|
||||
'char bool short int __int32 __int64 __int8 __int16 long float double __wchar_t ' +
|
||||
'clock_t _complex _dev_t _diskfree_t div_t ldiv_t _exception _EXCEPTION_POINTERS ' +
|
||||
'FILE _finddata_t _finddatai64_t _wfinddata_t _wfinddatai64_t __finddata64_t ' +
|
||||
'__wfinddata64_t _FPIEEE_RECORD fpos_t _HEAPINFO _HFILE lconv intptr_t ' +
|
||||
'jmp_buf mbstate_t _off_t _onexit_t _PNH ptrdiff_t _purecall_handler ' +
|
||||
'sig_atomic_t size_t _stat __stat64 _stati64 terminate_function ' +
|
||||
'time_t __time64_t _timeb __timeb64 tm uintptr_t _utimbuf ' +
|
||||
'va_list wchar_t wctrans_t wctype_t wint_t signed';
|
||||
|
||||
var keywords = 'break case catch class const __finally __exception __try ' +
|
||||
'const_cast continue private public protected __declspec ' +
|
||||
'default delete deprecated dllexport dllimport do dynamic_cast ' +
|
||||
'else enum explicit extern if for friend goto inline ' +
|
||||
'mutable naked namespace new noinline noreturn nothrow ' +
|
||||
'register reinterpret_cast return selectany ' +
|
||||
'sizeof static static_cast struct switch template this ' +
|
||||
'thread throw true false try typedef typeid typename union ' +
|
||||
'using uuid virtual void volatile whcar_t while';
|
||||
|
||||
var functions = 'assert isalnum isalpha iscntrl isdigit isgraph islower isprint' +
|
||||
'ispunct isspace isupper isxdigit tolower toupper errno localeconv ' +
|
||||
'setlocale acos asin atan atan2 ceil cos cosh exp fabs floor fmod ' +
|
||||
'frexp ldexp log log10 modf pow sin sinh sqrt tan tanh jmp_buf ' +
|
||||
'longjmp setjmp raise signal sig_atomic_t va_arg va_end va_start ' +
|
||||
'clearerr fclose feof ferror fflush fgetc fgetpos fgets fopen ' +
|
||||
'fprintf fputc fputs fread freopen fscanf fseek fsetpos ftell ' +
|
||||
'fwrite getc getchar gets perror printf putc putchar puts remove ' +
|
||||
'rename rewind scanf setbuf setvbuf sprintf sscanf tmpfile tmpnam ' +
|
||||
'ungetc vfprintf vprintf vsprintf abort abs atexit atof atoi atol ' +
|
||||
'bsearch calloc div exit free getenv labs ldiv malloc mblen mbstowcs ' +
|
||||
'mbtowc qsort rand realloc srand strtod strtol strtoul system ' +
|
||||
'wcstombs wctomb memchr memcmp memcpy memmove memset strcat strchr ' +
|
||||
'strcmp strcoll strcpy strcspn strerror strlen strncat strncmp ' +
|
||||
'strncpy strpbrk strrchr strspn strstr strtok strxfrm asctime ' +
|
||||
'clock ctime difftime gmtime localtime mktime strftime time';
|
||||
|
||||
this.regexList = [
|
||||
{ regex: SyntaxHighlighter.regexLib.singleLineCComments, css: 'comments' }, // one line comments
|
||||
{ regex: SyntaxHighlighter.regexLib.multiLineCComments, css: 'comments' }, // multiline comments
|
||||
{ regex: SyntaxHighlighter.regexLib.doubleQuotedString, css: 'string' }, // strings
|
||||
{ regex: SyntaxHighlighter.regexLib.singleQuotedString, css: 'string' }, // strings
|
||||
{ regex: /^ *#.*/gm, css: 'preprocessor' },
|
||||
{ regex: new RegExp(this.getKeywords(datatypes), 'gm'), css: 'color1 bold' },
|
||||
{ regex: new RegExp(this.getKeywords(functions), 'gm'), css: 'functions bold' },
|
||||
{ regex: new RegExp(this.getKeywords(keywords), 'gm'), css: 'keyword bold' }
|
||||
];
|
||||
};
|
||||
|
||||
Brush.prototype = new SyntaxHighlighter.Highlighter();
|
||||
Brush.aliases = ['cpp', 'c'];
|
||||
|
||||
SyntaxHighlighter.brushes.Cpp = Brush;
|
||||
|
||||
// CommonJS
|
||||
typeof(exports) != 'undefined' ? exports.Brush = Brush : null;
|
||||
})();
|
||||
@@ -0,0 +1,328 @@
|
||||
/**
|
||||
* SyntaxHighlighter
|
||||
* http://alexgorbatchev.com/SyntaxHighlighter
|
||||
*
|
||||
* SyntaxHighlighter is donationware. If you are using it, please donate.
|
||||
* http://alexgorbatchev.com/SyntaxHighlighter/donate.html
|
||||
*
|
||||
* @version
|
||||
* 3.0.83 (July 02 2010)
|
||||
*
|
||||
* @copyright
|
||||
* Copyright (C) 2004-2010 Alex Gorbatchev.
|
||||
*
|
||||
* @license
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
*/
|
||||
.syntaxhighlighter a,
|
||||
.syntaxhighlighter div,
|
||||
.syntaxhighlighter code,
|
||||
.syntaxhighlighter table,
|
||||
.syntaxhighlighter table td,
|
||||
.syntaxhighlighter table tr,
|
||||
.syntaxhighlighter table tbody,
|
||||
.syntaxhighlighter table thead,
|
||||
.syntaxhighlighter table caption,
|
||||
.syntaxhighlighter textarea {
|
||||
-moz-border-radius: 0 0 0 0 !important;
|
||||
-webkit-border-radius: 0 0 0 0 !important;
|
||||
background: none !important;
|
||||
border: 0 !important;
|
||||
bottom: auto !important;
|
||||
float: none !important;
|
||||
height: auto !important;
|
||||
left: auto !important;
|
||||
line-height: 1.1em !important;
|
||||
margin: 0 !important;
|
||||
outline: 0 !important;
|
||||
overflow: visible !important;
|
||||
padding: 0 !important;
|
||||
position: static !important;
|
||||
right: auto !important;
|
||||
text-align: left !important;
|
||||
top: auto !important;
|
||||
vertical-align: baseline !important;
|
||||
width: auto !important;
|
||||
box-sizing: content-box !important;
|
||||
font-family: "Consolas", "Bitstream Vera Sans Mono", "Courier New", Courier, monospace !important;
|
||||
font-weight: normal !important;
|
||||
font-style: normal !important;
|
||||
font-size: 10pt !important;
|
||||
min-height: inherit !important;
|
||||
min-height: auto !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter {
|
||||
width: 100% !important;
|
||||
margin: 1em 0 1em 0 !important;
|
||||
position: relative !important;
|
||||
overflow: auto !important;
|
||||
font-size: 1em !important;
|
||||
}
|
||||
.syntaxhighlighter.source {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
.syntaxhighlighter .bold {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
.syntaxhighlighter .italic {
|
||||
font-style: italic !important;
|
||||
}
|
||||
.syntaxhighlighter .line {
|
||||
white-space: pre !important;
|
||||
}
|
||||
.syntaxhighlighter table {
|
||||
width: 100% !important;
|
||||
}
|
||||
.syntaxhighlighter table caption {
|
||||
text-align: left !important;
|
||||
padding: .5em 0 0.5em 1em !important;
|
||||
}
|
||||
.syntaxhighlighter table td.code {
|
||||
width: 100% !important;
|
||||
}
|
||||
.syntaxhighlighter table td.code .container {
|
||||
position: relative !important;
|
||||
}
|
||||
.syntaxhighlighter table td.code .container textarea {
|
||||
box-sizing: border-box !important;
|
||||
position: absolute !important;
|
||||
left: 0 !important;
|
||||
top: 0 !important;
|
||||
width: 100% !important;
|
||||
height: 100% !important;
|
||||
border: none !important;
|
||||
background: white !important;
|
||||
padding-left: 1em !important;
|
||||
overflow: hidden !important;
|
||||
white-space: pre !important;
|
||||
}
|
||||
.syntaxhighlighter table td.gutter .line {
|
||||
text-align: right !important;
|
||||
padding: 0 0.5em 0 1em !important;
|
||||
}
|
||||
.syntaxhighlighter table td.code .line {
|
||||
padding: 0 1em !important;
|
||||
}
|
||||
.syntaxhighlighter.nogutter td.code .container textarea, .syntaxhighlighter.nogutter td.code .line {
|
||||
padding-left: 0em !important;
|
||||
}
|
||||
.syntaxhighlighter.show {
|
||||
display: block !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed table {
|
||||
display: none !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar {
|
||||
padding: 0.1em 0.8em 0em 0.8em !important;
|
||||
font-size: 1em !important;
|
||||
position: static !important;
|
||||
width: auto !important;
|
||||
height: auto !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar span {
|
||||
display: inline !important;
|
||||
margin-right: 1em !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar span a {
|
||||
padding: 0 !important;
|
||||
display: none !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar span a.expandSource {
|
||||
display: inline !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar {
|
||||
position: absolute !important;
|
||||
right: 1px !important;
|
||||
top: 1px !important;
|
||||
width: 11px !important;
|
||||
height: 11px !important;
|
||||
font-size: 10px !important;
|
||||
z-index: 10 !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar span.title {
|
||||
display: inline !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar a {
|
||||
display: block !important;
|
||||
text-align: center !important;
|
||||
text-decoration: none !important;
|
||||
padding-top: 1px !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar a.expandSource {
|
||||
display: none !important;
|
||||
}
|
||||
.syntaxhighlighter.ie {
|
||||
font-size: .9em !important;
|
||||
padding: 1px 0 1px 0 !important;
|
||||
}
|
||||
.syntaxhighlighter.ie .toolbar {
|
||||
line-height: 8px !important;
|
||||
}
|
||||
.syntaxhighlighter.ie .toolbar a {
|
||||
padding-top: 0px !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .line.alt1 .content,
|
||||
.syntaxhighlighter.printing .line.alt2 .content,
|
||||
.syntaxhighlighter.printing .line.highlighted .number,
|
||||
.syntaxhighlighter.printing .line.highlighted.alt1 .content,
|
||||
.syntaxhighlighter.printing .line.highlighted.alt2 .content {
|
||||
background: none !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .line .number {
|
||||
color: #bbbbbb !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .line .content {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .toolbar {
|
||||
display: none !important;
|
||||
}
|
||||
.syntaxhighlighter.printing a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .plain, .syntaxhighlighter.printing .plain a {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .comments, .syntaxhighlighter.printing .comments a {
|
||||
color: #008200 !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .string, .syntaxhighlighter.printing .string a {
|
||||
color: blue !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .keyword {
|
||||
color: #006699 !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .preprocessor {
|
||||
color: gray !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .variable {
|
||||
color: #aa7700 !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .value {
|
||||
color: #009900 !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .functions {
|
||||
color: #ff1493 !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .constants {
|
||||
color: #0066cc !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .script {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .color1, .syntaxhighlighter.printing .color1 a {
|
||||
color: gray !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .color2, .syntaxhighlighter.printing .color2 a {
|
||||
color: #ff1493 !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .color3, .syntaxhighlighter.printing .color3 a {
|
||||
color: red !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .break, .syntaxhighlighter.printing .break a {
|
||||
color: black !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter {
|
||||
background-color: white !important;
|
||||
}
|
||||
.syntaxhighlighter .line.alt1 {
|
||||
background-color: white !important;
|
||||
}
|
||||
.syntaxhighlighter .line.alt2 {
|
||||
background-color: white !important;
|
||||
}
|
||||
.syntaxhighlighter .line.highlighted.alt1, .syntaxhighlighter .line.highlighted.alt2 {
|
||||
background-color: #e0e0e0 !important;
|
||||
}
|
||||
.syntaxhighlighter .line.highlighted.number {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter table caption {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter .gutter {
|
||||
color: #afafaf !important;
|
||||
}
|
||||
.syntaxhighlighter .gutter .line {
|
||||
border-right: 3px solid #6ce26c !important;
|
||||
}
|
||||
.syntaxhighlighter .gutter .line.highlighted {
|
||||
background-color: #6ce26c !important;
|
||||
color: white !important;
|
||||
}
|
||||
.syntaxhighlighter.printing .line .content {
|
||||
border: none !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed {
|
||||
overflow: visible !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar {
|
||||
color: blue !important;
|
||||
background: white !important;
|
||||
border: 1px solid #6ce26c !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar a {
|
||||
color: blue !important;
|
||||
}
|
||||
.syntaxhighlighter.collapsed .toolbar a:hover {
|
||||
color: red !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar {
|
||||
color: white !important;
|
||||
background: #6ce26c !important;
|
||||
border: none !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar a {
|
||||
color: white !important;
|
||||
}
|
||||
.syntaxhighlighter .toolbar a:hover {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter .plain, .syntaxhighlighter .plain a {
|
||||
color: black !important;
|
||||
}
|
||||
.syntaxhighlighter .comments, .syntaxhighlighter .comments a {
|
||||
color: #008200 !important;
|
||||
}
|
||||
.syntaxhighlighter .string, .syntaxhighlighter .string a {
|
||||
color: blue !important;
|
||||
}
|
||||
.syntaxhighlighter .keyword {
|
||||
color: #006699 !important;
|
||||
}
|
||||
.syntaxhighlighter .preprocessor {
|
||||
color: gray !important;
|
||||
}
|
||||
.syntaxhighlighter .variable {
|
||||
color: #aa7700 !important;
|
||||
}
|
||||
.syntaxhighlighter .value {
|
||||
color: #009900 !important;
|
||||
}
|
||||
.syntaxhighlighter .functions {
|
||||
color: #ff1493 !important;
|
||||
}
|
||||
.syntaxhighlighter .constants {
|
||||
color: #0066cc !important;
|
||||
}
|
||||
.syntaxhighlighter .script {
|
||||
font-weight: bold !important;
|
||||
color: #006699 !important;
|
||||
background-color: none !important;
|
||||
}
|
||||
.syntaxhighlighter .color1, .syntaxhighlighter .color1 a {
|
||||
color: gray !important;
|
||||
}
|
||||
.syntaxhighlighter .color2, .syntaxhighlighter .color2 a {
|
||||
color: #ff1493 !important;
|
||||
}
|
||||
.syntaxhighlighter .color3, .syntaxhighlighter .color3 a {
|
||||
color: red !important;
|
||||
}
|
||||
|
||||
.syntaxhighlighter .keyword {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
KIT.FileViewer = {
|
||||
|
||||
view : null,
|
||||
|
||||
lastFile : null,
|
||||
lastLines : [],
|
||||
|
||||
init : function( view ) {
|
||||
this.view = view;
|
||||
|
||||
SyntaxHighlighter.defaults['tab-size'] = 2;
|
||||
SyntaxHighlighter.defaults['toolbar'] = false;
|
||||
SyntaxHighlighter.all();
|
||||
},
|
||||
|
||||
showNavigation : function( data ) {
|
||||
var name;
|
||||
var that = this;
|
||||
for ( var i = data.length - 1; i >= 0; i-- ) {
|
||||
var fileName = data[i].name;
|
||||
name = fileName.split( '.' )[0];
|
||||
$( '<div class="button" id="' + name + '_button">' ).text( fileName ).appendTo( '#header' ).click( function( name ) {
|
||||
return function() {
|
||||
KIT.FileViewer.showFile( name );
|
||||
}
|
||||
}( name ));
|
||||
|
||||
if ( i === 0 ) {
|
||||
this.showFile( name );
|
||||
}
|
||||
|
||||
$( '#' + name + ' .syntaxhighlighter .code .line' ).click( function( name ) {
|
||||
return function() {
|
||||
var lineNumber = parseInt( $( this ).attr( 'class' ).substring( 11 ) );
|
||||
that.view.activateLocation( new KIT.Location( name, lineNumber ) );
|
||||
}
|
||||
}( name ));
|
||||
}
|
||||
},
|
||||
|
||||
resetLast : function() {
|
||||
if ( this.lastLines.length ) {
|
||||
for ( var i = 0; i < this.lastLines.length; i++ ) {
|
||||
$( '#' + this.lastFile + ' .code .number' + this.lastLines[i] ).removeClass( 'highlighted' );
|
||||
}
|
||||
this.lastLines = [];
|
||||
}
|
||||
},
|
||||
|
||||
showFile : function( file ) {
|
||||
this.resetLast();
|
||||
|
||||
if ( this.lastFile === file ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.lastFile ) {
|
||||
$( '#' + this.lastFile ).hide();
|
||||
$( '#' + this.lastFile + '_button' ).removeClass( 'selected' );
|
||||
}
|
||||
|
||||
$( '#' + file ).show();
|
||||
$( '#' + file + '_button' ).toggleClass( 'selected' );
|
||||
this.lastFile = file;
|
||||
},
|
||||
|
||||
addLocation : function( location ) {
|
||||
if ( this.lastFile !== location.fileName ) {
|
||||
this.showFile( location.fileName );
|
||||
}
|
||||
this.showLine( location.lineNumber );
|
||||
},
|
||||
|
||||
addLocations : function( locations ) {
|
||||
for ( var i = 0; i < locations.length; i++ ) {
|
||||
if ( this.lastFile !== locations[i].fileName ) {
|
||||
this.showFile( locations[i].fileName );
|
||||
}
|
||||
this.showLine( locations[i].lineNumber );
|
||||
}
|
||||
},
|
||||
|
||||
showLocation : function( location ) {
|
||||
this.showFile( location.fileName );
|
||||
this.showLine( location.lineNumber );
|
||||
this.scrollToLine();
|
||||
},
|
||||
|
||||
showLocations : function( locations ) {
|
||||
this.showFile( locations[0].fileName );
|
||||
for ( var i = 0; i < locations.length; i++ ) {
|
||||
this.showLine( locations[i].lineNumber );
|
||||
}
|
||||
this.scrollToLine();
|
||||
},
|
||||
|
||||
showLine : function( line ) {
|
||||
$( '#' + this.lastFile + ' .code .number' + line ).addClass( 'highlighted' );
|
||||
this.lastLines.push( line );
|
||||
},
|
||||
|
||||
scrollToLine : function() {
|
||||
if ( this.lastLines.length ) {
|
||||
$( '#wrapper' ).scrollTo( '#' + this.lastFile + ' .code .number' + this.lastLines[0], { offset : -200 } );
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,144 @@
|
||||
"use strict";
|
||||
|
||||
KIT.Interpreter = {
|
||||
visibility : KIT.Visibility.None,
|
||||
|
||||
fileName : null,
|
||||
|
||||
createProgramModel : function( data ) {
|
||||
var program = new KIT.Model.Program();
|
||||
|
||||
for ( var i = 0; i < data.length; i++ ) {
|
||||
this.parseNode( data[i], program, program );
|
||||
}
|
||||
|
||||
return program;
|
||||
},
|
||||
|
||||
parseNode : function( node, program, namespace ) {
|
||||
if ( !this[node.type] ) {
|
||||
console.error( 'Unknown node type', node.type, node );
|
||||
return;
|
||||
}
|
||||
|
||||
this[node.type]( node, program, namespace );
|
||||
},
|
||||
|
||||
file : function( node, program, namespace ) {
|
||||
this.fileName = node.name.split( '.' )[0];
|
||||
this.parseContent( node.content, program, namespace );
|
||||
},
|
||||
|
||||
parseContent : function( content, program, namespace ) {
|
||||
if ( !content ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( var i = 0; i < content.length; i++ ) {
|
||||
this.parseNode( content[i], program, namespace );
|
||||
}
|
||||
},
|
||||
|
||||
class : function( node, program, namespace ) {
|
||||
var classModel = namespace.createClass( node.name, this.createLocation( node.line ), this.visibility );
|
||||
|
||||
if ( node.base ) {
|
||||
program.createInheritance( program.getClass( node.base ), classModel, this.createLocation( node.line ) );
|
||||
}
|
||||
|
||||
if ( node.content ) {
|
||||
var visibility = this.visibility;
|
||||
|
||||
if ( node.content.public ) {
|
||||
this.visibility = KIT.Visibility.Public;
|
||||
this.parseContent( node.content.public, program, classModel );
|
||||
}
|
||||
|
||||
if ( node.content.private ) {
|
||||
this.visibility = KIT.Visibility.Private;
|
||||
this.parseContent( node.content.private, program, classModel );
|
||||
}
|
||||
|
||||
this.visibility = visibility;
|
||||
}
|
||||
},
|
||||
|
||||
member : function( node, program, namespace ) {
|
||||
var member = namespace.createMember( node.name, this.createLocation( node.line ), this.visibility, this.getAbstraction( node ) );
|
||||
if ( node.class ) {
|
||||
member.typeName = node.class;
|
||||
program.createInstantiation( member, program.getClass( node.class ), this.createLocation( node.line ) );
|
||||
}
|
||||
},
|
||||
|
||||
method : function( node, program, namespace ) {
|
||||
var methodModel = namespace.createMethod( node.name, this.createLocation( node.line ), this.visibility, this.getAbstraction( node ) );
|
||||
this.addParams( methodModel, node, program );
|
||||
this.parseContent( node.content, program, methodModel );
|
||||
},
|
||||
|
||||
getAbstraction : function( node ) {
|
||||
switch ( node.abstraction ) {
|
||||
case 'static' : return KIT.Abstraction.Static;
|
||||
case 'virtual' : return KIT.Abstraction.Virtual;
|
||||
case 'pure_virtual' : return KIT.Abstraction.PureVirtual;
|
||||
default : return KIT.Abstraction.None;
|
||||
}
|
||||
},
|
||||
|
||||
use : function( node, program, namespace ) {
|
||||
var location = this.createLocation( node.line );
|
||||
if ( node.class && node.member ) {
|
||||
program.createUsage( namespace, program.getClass( node.class ).getMember( node.member ), location );
|
||||
} else if ( node.member ) {
|
||||
program.createUsage( namespace, namespace.parent.getMember( node.member ), location );
|
||||
} else if ( node.variable ) {
|
||||
program.createUsage( namespace, program.getVariable( node.variable ), location );
|
||||
} else {
|
||||
program.createUsage( namespace, program.getClass( node.class ), location );
|
||||
}
|
||||
},
|
||||
|
||||
call : function( node, program, namespace ) {
|
||||
var location = this.createLocation( node.line );
|
||||
if ( node.class ) {
|
||||
program.createCall( namespace, program.getClass( node.class ).getMethod( node.method ), location );
|
||||
} else if ( node.function ) {
|
||||
program.createCall( namespace, program.getFunction( node.function ), location );
|
||||
} else {
|
||||
program.createCall( namespace, namespace.parent.getMethod( node.method ), location );
|
||||
}
|
||||
},
|
||||
|
||||
variable : function( node, program, namespace ) {
|
||||
var variable = namespace.createVariable( node.name, this.createLocation( node.line ) );
|
||||
if ( node.class ) {
|
||||
variable.typeName = node.class;
|
||||
program.createInstantiation( variable, program.getClass( node.class ), this.createLocation( node.line ) );
|
||||
}
|
||||
},
|
||||
|
||||
function : function( node, program, namespace ) {
|
||||
var functionModel = program.createFunction( node.name, this.createLocation( node.line ) );
|
||||
this.addParams( functionModel, node, program );
|
||||
this.parseContent( node.content, program, functionModel );
|
||||
},
|
||||
|
||||
createLocation : function( lineNumber ) {
|
||||
return new KIT.Location( this.fileName, lineNumber );
|
||||
},
|
||||
|
||||
addParams : function( functionModel, node, program ) {
|
||||
if ( node.params ) {
|
||||
for ( var i = 0; i < node.params.length; i++ ) {
|
||||
program.createUsage( functionModel, program.getClass( node.params[i] ), this.createLocation( node.line ) );
|
||||
}
|
||||
functionModel.params = node.params;
|
||||
}
|
||||
|
||||
if ( node.return ) {
|
||||
program.createUsage( functionModel, program.getClass( node.return ), this.createLocation( node.line ) );
|
||||
functionModel.returnValue = node.return;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
var KIT = {
|
||||
Types : {
|
||||
Variable : { name : 'variable' },
|
||||
Usage : { name : 'usage' },
|
||||
Function : { name : 'function' },
|
||||
Call : { name : 'call' },
|
||||
Class : { name : 'class' },
|
||||
Member : { name : 'member' },
|
||||
Method : { name : 'method' },
|
||||
Inheritance : { name : 'inheritance' },
|
||||
Instantiation : { name : 'instantiation' },
|
||||
Aggregation : { name : 'aggregation' },
|
||||
Program : { name : 'program' }
|
||||
},
|
||||
|
||||
Visibility : {
|
||||
None : 0,
|
||||
Private : 1,
|
||||
Protected : 2,
|
||||
Public : 3
|
||||
},
|
||||
|
||||
Abstraction : {
|
||||
None : 0,
|
||||
Static : 1,
|
||||
Virtual : 2,
|
||||
PureVirtual : 3
|
||||
},
|
||||
|
||||
Model : {},
|
||||
View : {}
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
KIT.Location = function( fileName, lineNumber ) {
|
||||
this.fileName = fileName;
|
||||
this.lineNumber = lineNumber
|
||||
};
|
||||
|
||||
KIT.Location.prototype = {
|
||||
equals : function( location ) {
|
||||
return this.fileName === location.fileName && this.lineNumber === location.lineNumber;
|
||||
},
|
||||
|
||||
highlight : function() {
|
||||
$( '#' + this.fileName + ' .gutter .number' + this.lineNumber ).addClass( 'highlighted' );
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
function main( data ) {
|
||||
|
||||
var idx;
|
||||
|
||||
var width = $( '#paper' ).width() - $('#wrapper').width() - 2;
|
||||
var height = $( '#paper' ).height();
|
||||
var paper = Raphael( 'paper', width, height );
|
||||
|
||||
if ( getURLParams().sample ) {
|
||||
data = [data.shift()];
|
||||
idx = 5;
|
||||
} else {
|
||||
data.shift();
|
||||
idx = 15;
|
||||
}
|
||||
|
||||
var programModel = KIT.Interpreter.createProgramModel( data );
|
||||
var programView = new KIT.View.Program( programModel );
|
||||
programView.initView( paper, data );
|
||||
|
||||
setTimeout( function() {
|
||||
programView.activeView = programView.nodeViews[idx];
|
||||
}, 100);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
KIT.Model.Class = function( name ) {
|
||||
KIT.Model.Node.call( this, name );
|
||||
KIT.Model.Graph.call( this );
|
||||
|
||||
this.baseClass_ = null;
|
||||
|
||||
this.visibility_ = KIT.Visibility.Public;
|
||||
this.abstraction = KIT.Abstraction.None;
|
||||
};
|
||||
|
||||
KIT.Model.Graph.prototype.__proto__ = KIT.Model.Node.prototype;
|
||||
|
||||
KIT.Model.Class.prototype = {
|
||||
__proto__ : KIT.Model.Graph.prototype,
|
||||
|
||||
type : KIT.Types.Class,
|
||||
|
||||
get baseClass() {
|
||||
return this.baseClass_;
|
||||
},
|
||||
|
||||
set baseClass( baseClass ) {
|
||||
if ( this.baseClass_ ) {
|
||||
console.error( 'base class already set!');
|
||||
}
|
||||
this.baseClass_ = baseClass;
|
||||
},
|
||||
|
||||
createNode : function( type, name, location, visibility, abstraction ) {
|
||||
var node = KIT.Model.Graph.prototype.createNode.call( this, type, name, location );
|
||||
if ( visibility ) {
|
||||
node.visibility = visibility;
|
||||
}
|
||||
if ( abstraction ) {
|
||||
node.abstraction = abstraction;
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
getMember : function( name ) {
|
||||
return this.getOrCreateNode( KIT.Model.Member, name );
|
||||
},
|
||||
|
||||
createMember : function( name, location, visibility, abstraction ) {
|
||||
return this.createNode( KIT.Model.Member, name, location, visibility, abstraction );
|
||||
},
|
||||
|
||||
getMethod : function( name ) {
|
||||
return this.getOrCreateNode( KIT.Model.Method, name );
|
||||
},
|
||||
|
||||
createMethod : function( name, location, visibility, abstraction ) {
|
||||
return this.createNode( KIT.Model.Method, name, location, visibility, abstraction );
|
||||
},
|
||||
|
||||
createClass : function( name, location, visibility, abstraction ) {
|
||||
return this.createNode( KIT.Model.Class, name, location, visibility, abstraction );
|
||||
},
|
||||
|
||||
highlightLocation : function() {
|
||||
KIT.Model.Node.prototype.highlightLocation.call( this );
|
||||
KIT.Model.Graph.prototype.highlightLocation.call( this );
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,93 @@
|
||||
KIT.Model.Edge = function( name, from, to ) {
|
||||
this.name_ = name;
|
||||
|
||||
this.from_ = from;
|
||||
this.to_ = to;
|
||||
|
||||
this.locations_ = [];
|
||||
|
||||
from.addEdge( this );
|
||||
to.addEdge( this );
|
||||
};
|
||||
|
||||
KIT.Model.Edge.prototype = {
|
||||
|
||||
get name() {
|
||||
return this.name_;
|
||||
},
|
||||
|
||||
get shortName() {
|
||||
return this.name_;
|
||||
},
|
||||
|
||||
get from() {
|
||||
return this.from_;
|
||||
},
|
||||
|
||||
get to() {
|
||||
return this.to_;
|
||||
},
|
||||
|
||||
addLocation : function( location ) {
|
||||
this.locations_.push( location );
|
||||
},
|
||||
|
||||
get locations() {
|
||||
return this.locations_;
|
||||
},
|
||||
|
||||
highlightLocation : function() {
|
||||
for ( var i = 0; i < this.locations_.length; i++ ) {
|
||||
this.locations_[i].highlight();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Derived models.
|
||||
|
||||
KIT.Model.Usage = function( name, usingNode, usedNode ) {
|
||||
KIT.Model.Edge.call( this, name, usingNode, usedNode );
|
||||
};
|
||||
|
||||
KIT.Model.Usage.prototype = {
|
||||
__proto__ : KIT.Model.Edge.prototype,
|
||||
|
||||
type : KIT.Types.Usage
|
||||
};
|
||||
|
||||
|
||||
KIT.Model.Call = function( name, caller, callee ) {
|
||||
KIT.Model.Edge.call( this, name, caller, callee );
|
||||
|
||||
this.abstraction = KIT.Abstraction.None;
|
||||
};
|
||||
|
||||
KIT.Model.Call.prototype = {
|
||||
__proto__ : KIT.Model.Edge.prototype,
|
||||
|
||||
type : KIT.Types.Call
|
||||
};
|
||||
|
||||
|
||||
KIT.Model.Inheritance = function( name, baseClass, derivedClass ) {
|
||||
KIT.Model.Edge.call( this, name, baseClass, derivedClass );
|
||||
|
||||
derivedClass.baseClass = baseClass;
|
||||
};
|
||||
|
||||
KIT.Model.Inheritance.prototype = {
|
||||
__proto__ : KIT.Model.Edge.prototype,
|
||||
|
||||
type : KIT.Types.Inheritance
|
||||
};
|
||||
|
||||
|
||||
KIT.Model.Instantiation = function( name, variable, classNode ) {
|
||||
KIT.Model.Edge.call( this, name, classNode, variable );
|
||||
};
|
||||
|
||||
KIT.Model.Instantiation.prototype = {
|
||||
__proto__ : KIT.Model.Edge.prototype,
|
||||
|
||||
type : KIT.Types.Instantiation
|
||||
};
|
||||
@@ -0,0 +1,110 @@
|
||||
KIT.Model.Graph = function() {
|
||||
this.nodes_ = [];
|
||||
this.edges_ = [];
|
||||
};
|
||||
|
||||
KIT.Model.Graph.prototype = {
|
||||
|
||||
get nodes() {
|
||||
return this.nodes_;
|
||||
},
|
||||
|
||||
get edges() {
|
||||
return this.edges_;
|
||||
},
|
||||
|
||||
findNode : function( name ) {
|
||||
return this.findFirstByKeyInArray( 'name_', name, this.nodes_ );
|
||||
},
|
||||
|
||||
getNode : function( name ) {
|
||||
var node = this.findNode( name );
|
||||
if ( !node ) {
|
||||
console.error( 'unknown node: ' + name );
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
getOrCreateNode : function( type, name, location ) {
|
||||
var node = this.findNode( name );
|
||||
|
||||
if ( !node && this.baseClass && !location ) {
|
||||
node = this.baseClass.findNode( name );
|
||||
}
|
||||
|
||||
if ( !node ) {
|
||||
node = new type( name );
|
||||
this.nodes_.push( node );
|
||||
node.parent = this;
|
||||
}
|
||||
|
||||
return node;
|
||||
},
|
||||
|
||||
createNode : function( type, name, location ) {
|
||||
var node = this.getOrCreateNode( type, name, location );
|
||||
node.location = location;
|
||||
return node;
|
||||
},
|
||||
|
||||
findEdge : function( name ) {
|
||||
return this.findFirstByKeyInArray( 'name_', name, this.edges_ );
|
||||
},
|
||||
|
||||
createEdge : function( type, from, to, location ) {
|
||||
if ( from.parent === to ) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var name = type.prototype.type.name + ':' + from.name + '->' + to.name;
|
||||
var edge = this.findFirstByKeyInArray( 'name_', name, this.edges_ );
|
||||
|
||||
if ( !edge ) {
|
||||
edge = new type( name, from, to );
|
||||
this.edges_.push( edge );
|
||||
}
|
||||
|
||||
edge.addLocation( location );
|
||||
|
||||
return edge;
|
||||
},
|
||||
|
||||
findFirstByKeyInArray : function( key, value, array ) {
|
||||
for ( var i = 0; i < array.length; i++ ) {
|
||||
if ( array[i][key] === value ) {
|
||||
return array[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
findAllByKeyInArray : function( key, value, array ) {
|
||||
var all = [];
|
||||
for ( var i = 0; i < array.length; i++ ) {
|
||||
if ( array[i][key] === value ) {
|
||||
all.push( array[i] );
|
||||
}
|
||||
}
|
||||
return all;
|
||||
},
|
||||
|
||||
addSearchData : function( data ) {
|
||||
KIT.Model.Node.prototype.addSearchData.call( this, data );
|
||||
|
||||
for ( var i = 0; i < this.nodes.length; i++ ) {
|
||||
this.nodes[i].addSearchData( data );
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
highlightLocation : function() {
|
||||
for ( var i = 0; i < this.nodes.length; i++ ) {
|
||||
this.nodes[i].highlightLocation();
|
||||
}
|
||||
|
||||
for ( var i = 0; i < this.edges.length; i++ ) {
|
||||
this.edges[i].highlightLocation();
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,222 @@
|
||||
KIT.Model.Node = function( name ) {
|
||||
this.edges_ = [];
|
||||
this.name_ = name;
|
||||
|
||||
this.parent_ = null;
|
||||
this.location_ = null;
|
||||
};
|
||||
|
||||
KIT.Model.Node.prototype = {
|
||||
|
||||
get name() {
|
||||
var parentName = this.parent.name;
|
||||
if ( parentName.length ) {
|
||||
return parentName + '::' + this.name_;
|
||||
}
|
||||
return this.name_;
|
||||
},
|
||||
|
||||
get shortName() {
|
||||
return this.name_;
|
||||
},
|
||||
|
||||
get parent() {
|
||||
return this.parent_;
|
||||
},
|
||||
|
||||
set parent( parent ) {
|
||||
this.parent_ = parent;
|
||||
},
|
||||
|
||||
get location() {
|
||||
return this.location_;
|
||||
},
|
||||
|
||||
set location( location ) {
|
||||
if ( this.location_ ) {
|
||||
console.error( 'Location already set!');
|
||||
}
|
||||
this.location_ = location;
|
||||
},
|
||||
|
||||
addEdge : function( edge ) {
|
||||
if ( edge.from === this ) {
|
||||
this.edges_.unshift( edge );
|
||||
} else if ( edge.to === this ) {
|
||||
this.edges_.push( edge );
|
||||
} else {
|
||||
console.error( 'This node is not associated with the edge' );
|
||||
}
|
||||
},
|
||||
|
||||
lastParent : function() {
|
||||
if ( this.parent.type !== KIT.Types.Program ) {
|
||||
return this.parent.lastParent();
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
getProgram : function() {
|
||||
if ( this.parent.type === KIT.Types.Program ) {
|
||||
return this.parent;
|
||||
}
|
||||
return this.parent.getProgram();
|
||||
},
|
||||
|
||||
addSearchData : function( data ) {
|
||||
var values;
|
||||
switch ( this.type ) {
|
||||
case KIT.Types.Class : values = data.classes; break;
|
||||
case KIT.Types.Variable : values = data.variables; break;
|
||||
case KIT.Types.Function : values = data.functions; break;
|
||||
case KIT.Types.Member : values = data.members; break;
|
||||
case KIT.Types.Method : values = data.methods; break;
|
||||
default: return;
|
||||
}
|
||||
|
||||
var tokens = [];
|
||||
var name = this.name;
|
||||
for ( var i = 0; i < name.length; i++ ) {
|
||||
tokens.push( name.substring( i ) );
|
||||
}
|
||||
|
||||
values.push(
|
||||
{
|
||||
value : name,
|
||||
tokens : tokens,
|
||||
model : this
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
highlightLocation : function() {
|
||||
if ( this.location ) {
|
||||
this.location.highlight();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Derived models.
|
||||
|
||||
KIT.Model.Function = function( name ) {
|
||||
KIT.Model.Node.call( this, name );
|
||||
|
||||
this.returnValue_ = null;
|
||||
this.params_ = null;
|
||||
};
|
||||
|
||||
KIT.Model.Function.prototype = {
|
||||
__proto__ : KIT.Model.Node.prototype,
|
||||
|
||||
type : KIT.Types.Function,
|
||||
|
||||
get returnValue() {
|
||||
return this.returnValue_;
|
||||
},
|
||||
|
||||
set returnValue( returnValue ) {
|
||||
this.returnValue_ = returnValue;
|
||||
},
|
||||
|
||||
get params() {
|
||||
return this.params_;
|
||||
},
|
||||
|
||||
set params( params ) {
|
||||
this.params_ = params;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
KIT.Model.Method = function( name ) {
|
||||
KIT.Model.Function.call( this, name );
|
||||
|
||||
this.visibility_ = KIT.Visibility.Public;
|
||||
this.abstraction_ = KIT.Abstraction.None;
|
||||
|
||||
this.virtuals = [];
|
||||
};
|
||||
|
||||
KIT.Model.Method.prototype = {
|
||||
__proto__ : KIT.Model.Function.prototype,
|
||||
|
||||
type : KIT.Types.Method,
|
||||
|
||||
get visibility() {
|
||||
return this.visibility_;
|
||||
},
|
||||
|
||||
set visibility( visibility ) {
|
||||
this.visibility_ = visibility;
|
||||
},
|
||||
|
||||
get abstraction() {
|
||||
return this.abstraction_;
|
||||
},
|
||||
|
||||
set abstraction( abstraction ) {
|
||||
this.abstraction_ = abstraction;
|
||||
|
||||
if ( abstraction === KIT.Abstraction.PureVirtual ) {
|
||||
this.parent.abstraction = KIT.Abstraction.PureVirtual;
|
||||
} else if ( abstraction === KIT.Abstraction.Virtual ) {
|
||||
var nodes = this.parent.baseClass.nodes;
|
||||
for ( var i = 0; i < nodes.length; i++ ) {
|
||||
if ( nodes[i].shortName === this.shortName ) {
|
||||
nodes[i].virtuals.push( this );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
KIT.Model.Variable = function( name ) {
|
||||
KIT.Model.Node.call( this, name );
|
||||
};
|
||||
|
||||
KIT.Model.Variable.prototype = {
|
||||
__proto__ : KIT.Model.Node.prototype,
|
||||
|
||||
type : KIT.Types.Variable
|
||||
};
|
||||
|
||||
|
||||
KIT.Model.Member = function( name ) {
|
||||
KIT.Model.Variable.call( this, name );
|
||||
|
||||
this.visibility_ = KIT.Visibility.Public;
|
||||
this.abstraction_ = KIT.Abstraction.None;
|
||||
|
||||
this.typeName_ = null;
|
||||
};
|
||||
|
||||
KIT.Model.Member.prototype = {
|
||||
__proto__ : KIT.Model.Variable.prototype,
|
||||
|
||||
type : KIT.Types.Member,
|
||||
|
||||
get visibility() {
|
||||
return this.visibility_;
|
||||
},
|
||||
|
||||
set visibility( visibility ) {
|
||||
this.visibility_ = visibility;
|
||||
},
|
||||
|
||||
get abstraction() {
|
||||
return this.abstraction_;
|
||||
},
|
||||
|
||||
set abstraction( abstraction ) {
|
||||
this.abstraction_ = abstraction;
|
||||
},
|
||||
|
||||
get typeName() {
|
||||
return this.typeName_;
|
||||
},
|
||||
|
||||
set typeName( typeName ) {
|
||||
this.typeName_ = typeName;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,108 @@
|
||||
KIT.Model.Program = function() {
|
||||
KIT.Model.Graph.call( this );
|
||||
};
|
||||
|
||||
KIT.Model.Program.prototype = {
|
||||
__proto__ : KIT.Model.Graph.prototype,
|
||||
|
||||
type : KIT.Types.Program,
|
||||
|
||||
get name() {
|
||||
return '';
|
||||
},
|
||||
|
||||
getClass : function( name ) {
|
||||
var names = name.split( '::' );
|
||||
if ( names.length === 2 ) {
|
||||
var classNode = this.getOrCreateNode( KIT.Model.Class, names[0] );
|
||||
return classNode.getOrCreateNode( KIT.Model.Class, names[1] );
|
||||
}
|
||||
|
||||
var node = this.findNode( name );
|
||||
if ( !node ) {
|
||||
var classes = this.findAllByKeyInArray( 'type', KIT.Types.Class, this.nodes_ );
|
||||
for ( var i = 0; i < classes.length; i++ ) {
|
||||
node = classes[i].findNode( name );
|
||||
if ( node ) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return this.getOrCreateNode( KIT.Model.Class, name );
|
||||
}
|
||||
return node;
|
||||
},
|
||||
|
||||
createClass : function( name, location ) {
|
||||
return this.createNode( KIT.Model.Class, name, location );
|
||||
},
|
||||
|
||||
getVariable : function( name ) {
|
||||
return this.getOrCreateNode( KIT.Model.Variable, name );
|
||||
},
|
||||
|
||||
createVariable : function( name, location ) {
|
||||
return this.createNode( KIT.Model.Variable, name, location );
|
||||
},
|
||||
|
||||
getFunction : function( name ) {
|
||||
return this.getOrCreateNode( KIT.Model.Function, name );
|
||||
},
|
||||
|
||||
createFunction : function( name, location ) {
|
||||
return this.createNode( KIT.Model.Function, name, location );
|
||||
},
|
||||
|
||||
createCall : function( from, to, location ) {
|
||||
var edge = this.createEdge( KIT.Model.Call, from, to, location );
|
||||
|
||||
if ( to.abstraction === KIT.Abstraction.PureVirtual ) {
|
||||
for ( var i = 0; i < to.virtuals.length; i++ ) {
|
||||
var e = this.createEdge( KIT.Model.Call, to, to.virtuals[i], location );
|
||||
e.abstraction = KIT.Abstraction.PureVirtual;
|
||||
}
|
||||
}
|
||||
|
||||
return edge;
|
||||
},
|
||||
|
||||
createInheritance : function( from, to, location ) {
|
||||
return this.createEdge( KIT.Model.Inheritance, from, to, location );
|
||||
},
|
||||
|
||||
createInstantiation : function( from, to, location ) {
|
||||
return this.createEdge( KIT.Model.Instantiation, from, to, location );
|
||||
},
|
||||
|
||||
createUsage : function( from, to, location ) {
|
||||
return this.createEdge( KIT.Model.Usage, from, to, location );
|
||||
},
|
||||
|
||||
searchData : function() {
|
||||
data = {
|
||||
classes : [],
|
||||
variables : [],
|
||||
functions : [],
|
||||
members : [],
|
||||
methods : []
|
||||
};
|
||||
|
||||
this.addSearchData( data );
|
||||
|
||||
function dataObject( name ) {
|
||||
return {
|
||||
name : name,
|
||||
local : data[name],
|
||||
header : '<p class="tt-header">' + name + '</p>',
|
||||
limit : 30
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
dataObject( 'classes' ),
|
||||
dataObject( 'variables' ),
|
||||
dataObject( 'functions' ),
|
||||
dataObject( 'members' ),
|
||||
dataObject( 'methods' )
|
||||
];
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,312 @@
|
||||
var RaphaelElementExtensions = {
|
||||
|
||||
stroke : function( color, width ) {
|
||||
if ( width ) {
|
||||
this.attr({
|
||||
'stroke-width' : width
|
||||
});
|
||||
}
|
||||
this.attr({
|
||||
stroke : 'rgba(0,0,0,1)'
|
||||
});
|
||||
return this.attr({
|
||||
stroke : color
|
||||
});
|
||||
},
|
||||
|
||||
noStroke : function() {
|
||||
return this.attr({
|
||||
stroke : null
|
||||
})
|
||||
},
|
||||
|
||||
fill : function( color ) {
|
||||
return this.attr({
|
||||
fill : color
|
||||
});
|
||||
},
|
||||
|
||||
color : function( color ) {
|
||||
this.stroke( color );
|
||||
this.fill( color );
|
||||
return this;
|
||||
},
|
||||
|
||||
code : function( size, color ) {
|
||||
return this.attr({
|
||||
font : size + 'px Consolas, monospace',
|
||||
// 'text-anchor' : 'start',
|
||||
fill : color
|
||||
});
|
||||
},
|
||||
|
||||
dash : function() {
|
||||
return this.attr({
|
||||
'stroke-dasharray' : ['- ']
|
||||
});
|
||||
},
|
||||
|
||||
noDash : function() {
|
||||
return this.attr({
|
||||
'stroke-dasharray' : []
|
||||
})
|
||||
},
|
||||
|
||||
round : function() {
|
||||
return this.attr({
|
||||
'stroke-linecap' : 'round',
|
||||
'stroke-linejoin' : 'round'
|
||||
});
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
RaphaelFunctionExtensions = {
|
||||
|
||||
line : function( x, y, x2, y2 ) {
|
||||
return this.path( ['M', x, y, 'L', x2, y2].join( ' ' ) );
|
||||
},
|
||||
|
||||
connection : function( bb1, bb2, endPointType, lineType ) {
|
||||
var points;
|
||||
var line;
|
||||
|
||||
switch ( endPointType ) {
|
||||
case 'middle' :
|
||||
points = this.getMidConnectionPoints_( bb1, bb2 );
|
||||
break;
|
||||
case 'same' :
|
||||
points = this.getSameConnectionPoints_( bb1, bb2 );
|
||||
break;
|
||||
case 'shortest' :
|
||||
points = this.getShortestConnectionPoints_( bb1, bb2 );
|
||||
break;
|
||||
case 'center' :
|
||||
points = this.getCenterPoints_( bb1, bb2 );
|
||||
break;
|
||||
default :
|
||||
console.error( 'End point type unknown', endPointType );
|
||||
break;
|
||||
}
|
||||
|
||||
switch ( lineType ) {
|
||||
case 'line' :
|
||||
line = this.createLine_( points );
|
||||
this.addNormal_( points );
|
||||
break;
|
||||
case 'wave' :
|
||||
line = this.createWave_( points );
|
||||
break;
|
||||
case 'bow' :
|
||||
line = this.createBow_( points );
|
||||
break;
|
||||
default :
|
||||
console.error( 'Line type unknown', lineType );
|
||||
break;
|
||||
}
|
||||
|
||||
line.start = points[0];
|
||||
line.end = points[1];
|
||||
|
||||
return line;
|
||||
},
|
||||
|
||||
arrow : function( point, length, width, closed ) {
|
||||
var p = point;
|
||||
var u = new Vector( point.nx, point.ny ).normalizeSelf();
|
||||
var a = u.rotate( TAU / 4 );
|
||||
|
||||
u.mulSelf( length );
|
||||
a.mulSelf( width );
|
||||
|
||||
return this.path( [
|
||||
'M', p.x, p.y,
|
||||
'l', u.x - a.x, u.y - a.y,
|
||||
closed ? 'l' : 'm', 2 * a.x, 2 * a.y,
|
||||
'L', p.x, p.y].join( ' ' ) );
|
||||
},
|
||||
|
||||
getMidPoints_ : function( bb ) {
|
||||
return [
|
||||
{x : bb.x + bb.width / 2, y : bb.y, nx : 0, ny : -1 },
|
||||
{x : bb.x2, y : bb.y + bb.height / 2, nx : 1, ny : 0 },
|
||||
{x : bb.x + bb.width / 2, y : bb.y2, nx : 0, ny : 1 },
|
||||
{x : bb.x, y : bb.y + bb.height / 2, nx : -1, ny : 0 }
|
||||
];
|
||||
},
|
||||
|
||||
getMidConnectionPoints_ : function( bb1, bb2 ) {
|
||||
var p1 = this.getMidPoints_( bb1 );
|
||||
var p2 = this.getMidPoints_( bb2 );
|
||||
|
||||
var vec = new Vector;
|
||||
var min = Infinity, a, b;
|
||||
for ( var i = 0; i < 4; i++ ) {
|
||||
for ( var j = 0; j < 4; j++ ) {
|
||||
vec.copy( p1[i] ).subSelf( p2[j] );
|
||||
var dist = vec.normSquared();
|
||||
if ( dist < min ) {
|
||||
min = dist;
|
||||
a = p1[i];
|
||||
b = p2[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [a, b];
|
||||
},
|
||||
|
||||
getSameConnectionPoints_ : function( bb1, bb2 ) {
|
||||
var p1 = this.getMidPoints_( bb1 );
|
||||
var p2 = this.getMidPoints_( bb2 );
|
||||
|
||||
var vec = new Vector;
|
||||
var min = Infinity, a, b;
|
||||
for ( var i = 0; i < 4; i++ ) {
|
||||
vec.copy( p1[i] ).subSelf( p2[i] );
|
||||
var dist = vec.normSquared();
|
||||
if ( dist < min ) {
|
||||
min = dist;
|
||||
a = p1[i];
|
||||
b = p2[i];
|
||||
}
|
||||
}
|
||||
return [a, b];
|
||||
},
|
||||
|
||||
getShortestConnectionPoints_ : function( bb1, bb2 ) {
|
||||
var p1 = { x : 0, y : 0, nx : 0, ny : 0 };
|
||||
var p2 = { x : 0, y : 0, nx : 0, ny : 0 };
|
||||
|
||||
var x1 = Math.max( bb1.x, bb2.x );
|
||||
var x2 = Math.min( bb1.x2, bb2.x2 );
|
||||
|
||||
if ( x1 < x2 ) {
|
||||
p1.x = p2.x = ( x1 + x2 ) / 2;
|
||||
p1.ny = p2.ny = 1;
|
||||
} else if ( bb1.x2 === x2 ) {
|
||||
p1.x = x2;
|
||||
p2.x = x1;
|
||||
p1.nx = p2.nx = 1;
|
||||
} else {
|
||||
p1.x = x1;
|
||||
p2.x = x2;
|
||||
p1.nx = p2.nx = 1;
|
||||
}
|
||||
|
||||
var y1 = Math.max( bb1.y, bb2.y );
|
||||
var y2 = Math.min( bb1.y2, bb2.y2 );
|
||||
|
||||
if ( y1 < y2 ) {
|
||||
p1.y = p2.y = ( y1 + y2 ) / 2;
|
||||
} else if ( bb1.y2 === y2 ) {
|
||||
p1.y = y2;
|
||||
p2.y = y1;
|
||||
} else {
|
||||
p1.y = y1;
|
||||
p2.y = y2;
|
||||
}
|
||||
|
||||
if ( bb1.y < bb2.y ) {
|
||||
p2.ny *= -1;
|
||||
} else {
|
||||
p1.ny *= -1;
|
||||
}
|
||||
|
||||
if ( bb1.x < bb2.x ) {
|
||||
p2.nx *= -1;
|
||||
} else {
|
||||
p1.nx *= -1;
|
||||
}
|
||||
|
||||
return [p1, p2];
|
||||
},
|
||||
|
||||
getCenterPoints_ : function( bb1, bb2 ) {
|
||||
return [
|
||||
{x : bb1.x + bb1.width / 2, y : bb1.y + bb1.height / 2, nx : 0, ny : 1 },
|
||||
{x : bb2.x + bb2.width / 2, y : bb2.y + bb2.height / 2, nx : 0, ny : -1 },
|
||||
];
|
||||
},
|
||||
|
||||
getNormal_ : function( points ) {
|
||||
return new Vector( points[1].x - points[0].x, points[1].y - points[0].y ).normalizeSelf();
|
||||
},
|
||||
|
||||
addNormal_ : function( points ) {
|
||||
var n = this.getNormal_( points );
|
||||
points[0].nx = n.x;
|
||||
points[0].ny = n.y;
|
||||
points[1].nx = -n.x;
|
||||
points[1].ny = -n.y;
|
||||
},
|
||||
|
||||
createLine_ : function( points ) {
|
||||
return this.path( ['M', points[1].x, points[1].y, 'L', points[0].x, points[0].y].join( ' ' ) );
|
||||
},
|
||||
|
||||
createWave_ : function( points ) {
|
||||
var x2, y2, x3, y3;
|
||||
if ( points[0].nx === 0 ) {
|
||||
x2 = points[0].x;
|
||||
y2 = ( points[0].y + points[1].y ) / 2;
|
||||
} else {
|
||||
x2 = ( points[0].x + points[1].x ) / 2;
|
||||
y2 = points[0].y;
|
||||
}
|
||||
if ( points[1].nx === 0 ) {
|
||||
x3 = points[1].x;
|
||||
y3 = ( points[0].y + points[1].y ) / 2;
|
||||
} else {
|
||||
x3 = ( points[0].x + points[1].x ) / 2;
|
||||
y3 = points[1].y;
|
||||
}
|
||||
return this.path( ['M', points[0].x, points[0].y, 'C', x2, y2, x3, y3, points[1].x, points[1].y].join( ' ' ) );
|
||||
},
|
||||
|
||||
createBow_ : function( points ) {
|
||||
var f = 3;
|
||||
if ( points[0].nx < 0 ) {
|
||||
f *= -1;
|
||||
}
|
||||
var mid = new Vector().copy( points[0] ).addSelf( points[1] ).divSelf( 2 );
|
||||
mid.x += clamp( f * Math.abs( points[0].y - points[1].y ), -200, 200 );
|
||||
return this.path( ['M', points[0].x, points[0].y, 'S', mid.x, mid.y, points[1].x, points[1].y].join( ' ' ) );
|
||||
},
|
||||
|
||||
|
||||
shortestTo : function( p, q ) {
|
||||
var vec = new Vector;
|
||||
var min = Infinity, r;
|
||||
for ( var i = 0; i < 4; i++ ) {
|
||||
vec.copy( p ).subSelf( q[i] );
|
||||
var d = vec.normSquared();
|
||||
if ( d < min ) {
|
||||
min = d;
|
||||
r = q[i];
|
||||
}
|
||||
}
|
||||
return r;
|
||||
},
|
||||
|
||||
shortest2 : function( obj1, obj2 ) {
|
||||
var p = this.shortestPoints( obj1, obj2 );
|
||||
p[1] = this.shortestTo( p[0], this.getPoints( obj2 ) );
|
||||
return this.path( ['M', p[1].x, p[1].y, 'L', p[0].x, p[0].y].join( ' ' ) );
|
||||
}
|
||||
};
|
||||
|
||||
extend( Raphael.el, RaphaelElementExtensions);
|
||||
extend( Raphael.fn, RaphaelFunctionExtensions);
|
||||
|
||||
function addToSet( name ) {
|
||||
Raphael.st[name] = function() {
|
||||
var args = arguments;
|
||||
return this.forEach( function( el ) {
|
||||
el[name].apply( el, args );
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
for (var key in RaphaelElementExtensions) {
|
||||
addToSet( key );
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
function bind(scope, fn) {
|
||||
|
||||
if ( fn ) {
|
||||
|
||||
return function() {
|
||||
|
||||
fn.apply(scope, arguments);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
function extend(destination, source) {
|
||||
|
||||
for (var key in source) {
|
||||
|
||||
if (source.hasOwnProperty(key)) {
|
||||
|
||||
destination[key] = source[key];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return destination;
|
||||
|
||||
};
|
||||
|
||||
function log() {
|
||||
|
||||
console.log.apply(console, arguments);
|
||||
|
||||
};
|
||||
|
||||
function clamp( x, a, b ) {
|
||||
|
||||
return x ? x < a ? a : x > b ? b : x : a;
|
||||
|
||||
};
|
||||
|
||||
function map( x, a1, a2, b1, b2 ) {
|
||||
|
||||
return ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ) + b1;
|
||||
|
||||
};
|
||||
|
||||
function checkAngle( angle ) {
|
||||
|
||||
if ( angle > Math.PI ) {
|
||||
|
||||
angle -= 2 * Math.PI;
|
||||
|
||||
} else if ( angle <= -Math.PI ) {
|
||||
|
||||
angle += 2 * Math.PI;
|
||||
|
||||
}
|
||||
|
||||
return angle;
|
||||
|
||||
};
|
||||
|
||||
function rand( min, max ) {
|
||||
|
||||
min = min || 0;
|
||||
max = max || 1;
|
||||
|
||||
return Math.random() * (max - min) + min;
|
||||
|
||||
};
|
||||
|
||||
function randInt( min, max ) {
|
||||
|
||||
return Math.floor( rand( min, max ) );
|
||||
|
||||
};
|
||||
|
||||
function randSign() {
|
||||
|
||||
return Math.random() > 0.5 ? 1 : -1;
|
||||
|
||||
};
|
||||
|
||||
function randBool() {
|
||||
|
||||
return Math.random() > 0.5;
|
||||
|
||||
};
|
||||
|
||||
window.TAU = 2 * Math.PI;
|
||||
|
||||
function toRad( deg ) {
|
||||
|
||||
return deg * TAU / 360;
|
||||
|
||||
};
|
||||
|
||||
function toDeg( rad ) {
|
||||
|
||||
return rad / TAU * 360;
|
||||
|
||||
};
|
||||
|
||||
Array.prototype.forEachApply = function( fn, a ) {
|
||||
|
||||
this.forEach( function( e ) {
|
||||
|
||||
e[fn].call( e, a );
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
Array.prototype.clone = function() {
|
||||
|
||||
return this.concat();
|
||||
|
||||
};
|
||||
|
||||
Array.prototype.shuffle = function() {
|
||||
|
||||
var i = this.length, j, swap;
|
||||
|
||||
while ( i-- > 0 ) {
|
||||
|
||||
j = Math.floor( Math.random() * ( i + 1 ) );
|
||||
|
||||
swap = this[i];
|
||||
this[i] = this[j];
|
||||
this[j] = swap;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
Array.max = function( array ) {
|
||||
|
||||
return Math.max.apply( Math, array );
|
||||
|
||||
};
|
||||
|
||||
Array.min = function( array ) {
|
||||
|
||||
return Math.min.apply( Math, array );
|
||||
|
||||
};
|
||||
|
||||
Array.prototype.unique = function() {
|
||||
var a = [];
|
||||
for ( var i = 0; i < this.length; i++ ) {
|
||||
if ( a.indexOf( this[i] ) === -1 ) {
|
||||
a.push( this[i] );
|
||||
}
|
||||
}
|
||||
return a;
|
||||
};
|
||||
|
||||
function getURLParams() {
|
||||
|
||||
var params = {},
|
||||
floatRegex = /^[-+]?\d*\.?\d+$/,
|
||||
results = window.location.href.match( /[^?&#]*=[^&#]*/g ) || [],
|
||||
a, i;
|
||||
|
||||
for ( i = 0; i < results.length; i++ ) {
|
||||
|
||||
a = results[i].split('=');
|
||||
|
||||
params[a[0]] = floatRegex.test( a[1] ) ? parseFloat( a[1] ) : a[1];
|
||||
|
||||
}
|
||||
|
||||
return params;
|
||||
|
||||
};
|
||||
@@ -0,0 +1,252 @@
|
||||
var Vector = function(x, y) {
|
||||
|
||||
return this.set(
|
||||
x || 0,
|
||||
y || 0
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
Vector.prototype = {
|
||||
|
||||
set: function(x, y) {
|
||||
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
copy: function(vector) {
|
||||
|
||||
return this.set(
|
||||
vector.x,
|
||||
vector.y
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
clone: function() {
|
||||
|
||||
return new Vector(
|
||||
this.x,
|
||||
this.y
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
add: function(vector) {
|
||||
|
||||
return new Vector(
|
||||
this.x + vector.x,
|
||||
this.y + vector.y
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
addSelf: function(vector) {
|
||||
|
||||
this.x += vector.x;
|
||||
this.y += vector.y;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
sub: function(vector) {
|
||||
|
||||
return new Vector(
|
||||
this.x - vector.x,
|
||||
this.y - vector.y
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
subSelf: function(vector) {
|
||||
|
||||
this.x -= vector.x;
|
||||
this.y -= vector.y;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
mul: function(value) {
|
||||
|
||||
return new Vector(
|
||||
this.x * value,
|
||||
this.y * value
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
mulSelf: function(value) {
|
||||
|
||||
this.x *= value;
|
||||
this.y *= value;
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
div: function(value) {
|
||||
|
||||
if (!value) {
|
||||
|
||||
return new Vector();
|
||||
|
||||
}
|
||||
|
||||
return new Vector(
|
||||
this.x / value,
|
||||
this.y / value
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
divSelf: function(value) {
|
||||
|
||||
if (value) {
|
||||
|
||||
this.x /= value;
|
||||
this.y /= value;
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
dot: function(vector) {
|
||||
|
||||
return (this.x * vector.x + this.y * vector.y);
|
||||
|
||||
},
|
||||
|
||||
normSquared: function() {
|
||||
|
||||
return (this.x * this.x + this.y * this.y);
|
||||
|
||||
},
|
||||
|
||||
norm: function() {
|
||||
|
||||
return Math.sqrt(this.normSquared());
|
||||
|
||||
},
|
||||
|
||||
normalize: function() {
|
||||
|
||||
return this.div(this.norm());
|
||||
|
||||
},
|
||||
|
||||
normalizeSelf: function() {
|
||||
|
||||
return this.divSelf(this.norm());
|
||||
|
||||
},
|
||||
|
||||
clamp: function(value) {
|
||||
|
||||
if (this.normSquared() > value * value) {
|
||||
|
||||
return this.normalize().mul(value);
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
clampSelf: function(value) {
|
||||
|
||||
if (this.normSquared() > value * value) {
|
||||
|
||||
return this.normalizeSelf().mulSelf(value);
|
||||
|
||||
}
|
||||
|
||||
return this;
|
||||
|
||||
},
|
||||
|
||||
angle: function(vector) {
|
||||
|
||||
if (vector) {
|
||||
|
||||
return Math.acos(this.dot(vector) / this.norm() / vector.norm());
|
||||
|
||||
} else {
|
||||
|
||||
return Math.atan2(this.y, this.x);
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
rotate: function(angle) {
|
||||
|
||||
return this.clone().rotateSelf(angle);
|
||||
|
||||
},
|
||||
|
||||
rotateSelf: function(angle) {
|
||||
|
||||
if ( !angle ) {
|
||||
|
||||
return this;
|
||||
|
||||
}
|
||||
|
||||
return this.set(
|
||||
Math.cos(angle) * this.x - Math.sin(angle) * this.y,
|
||||
Math.sin(angle) * this.x + Math.cos(angle) * this.y
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
round: function() {
|
||||
|
||||
return new Vector(
|
||||
Math.round( this.x ),
|
||||
Math.round( this.y )
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
roundSelf: function() {
|
||||
|
||||
return this.set(
|
||||
Math.round( this.x ),
|
||||
Math.round( this.y )
|
||||
);
|
||||
|
||||
},
|
||||
|
||||
string: function() {
|
||||
|
||||
return '( ' + this.x.toFixed( 5 ) + ' | ' + this.y.toFixed( 5 ) + ' )';
|
||||
|
||||
},
|
||||
|
||||
log: function() {
|
||||
|
||||
console.log( this.string() );
|
||||
|
||||
},
|
||||
|
||||
getData : function() {
|
||||
|
||||
return { x : this.x, y : this.y };
|
||||
|
||||
},
|
||||
|
||||
length : function() {
|
||||
|
||||
return Math.sqrt( this.x * this.x + this.y * this.y);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,151 @@
|
||||
KIT.View.AnimationLayout = function( program, center ) {
|
||||
this.program_ = program;
|
||||
this.center_ = center;
|
||||
|
||||
this.nodes_ = [];
|
||||
this.edges_ = [];
|
||||
|
||||
this.oldNodes_ = [];
|
||||
};
|
||||
|
||||
KIT.View.AnimationLayout.Node = function( nodeView, layout ) {
|
||||
this.view = nodeView.lastParent;
|
||||
this.layout_ = layout;
|
||||
|
||||
this.active = !!nodeView.activeChildren.length;
|
||||
this.wasVisible = false;
|
||||
this.isCenter = false;
|
||||
this.wasCenter = false;
|
||||
|
||||
this.position = null;
|
||||
|
||||
this.start = function() {
|
||||
if ( this.position ) {
|
||||
this.view.update();
|
||||
this.view.position = this.position;
|
||||
}
|
||||
this.position = null;
|
||||
}
|
||||
};
|
||||
|
||||
KIT.View.AnimationLayout.Edge = function( edgeView, from, to, layout ) {
|
||||
this.view = edgeView;
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.layout_ = layout;
|
||||
|
||||
this.start = function() {
|
||||
this.view.add();
|
||||
}
|
||||
};
|
||||
|
||||
KIT.View.AnimationLayout.prototype = {
|
||||
|
||||
start : function() {
|
||||
var center = this.center_.clone();
|
||||
var vector = new Vector( -1, 0 );
|
||||
var slots = [];
|
||||
|
||||
var cbCount = 0;
|
||||
var cb = bind( this, function() {
|
||||
cbCount--;
|
||||
if ( !cbCount ) {
|
||||
this.nodes_.forEach( function( n ) { n.start(); });
|
||||
this.edges_.forEach( function( e ) { e.start(); });
|
||||
}
|
||||
});
|
||||
|
||||
var hasActive = false;
|
||||
this.nodes_.forEach( function( n ) { if ( n.active ) hasActive = true; } );
|
||||
if ( ( !hasActive && this.nodes_.length > 2 ) || this.nodes_.length === 1 ) {
|
||||
this.nodes_[ Math.floor( this.nodes_.length / 2 ) ].active = true;
|
||||
}
|
||||
|
||||
if ( this.nodes_.length === 2 ) {
|
||||
vector.mulSelf( center.x );
|
||||
center.x += vector.norm() / 2;
|
||||
|
||||
slots.push( center.add( vector ) );
|
||||
slots.push( center );
|
||||
} else {
|
||||
var angle = TAU / ( this.nodes_.length - 1 );
|
||||
for ( var i = 0; i < this.nodes_.length - 1; i++ ) {
|
||||
var vec = vector.clone();
|
||||
vec.x *= center.x * 0.7;
|
||||
vec.y *= center.y * 0.7;
|
||||
slots.push( vec.addSelf( center ) );
|
||||
vector.rotateSelf( angle );
|
||||
}
|
||||
}
|
||||
|
||||
for ( var i = 0; i < this.nodes_.length; i++ ) {
|
||||
var node = this.nodes_[i];
|
||||
if ( !node.active && node.wasVisible && !node.wasCenter ) {
|
||||
var l = Infinity;
|
||||
var idx = -1;
|
||||
for ( var j = 0; j < slots.length; j++ ) {
|
||||
vector.copy( slots[j] ).subSelf( node.view.position );
|
||||
if ( vector.normSquared() < l ) {
|
||||
l = vector.normSquared();
|
||||
idx = j;
|
||||
}
|
||||
}
|
||||
node.position = slots.splice( idx, 1 )[0];
|
||||
}
|
||||
}
|
||||
|
||||
for ( var i = 0; i < this.nodes_.length; i++ ) {
|
||||
var node = this.nodes_[i];
|
||||
|
||||
if ( node.active && this.nodes_.length !== 2 ) {
|
||||
node.position = center;
|
||||
node.isCenter = true;
|
||||
} else if ( !node.position ) {
|
||||
node.position = slots.shift();
|
||||
}
|
||||
|
||||
if ( node.wasVisible ) {
|
||||
node.view.update();
|
||||
if ( node.view.animateTo( node.position, cb ) ) {
|
||||
cbCount++;
|
||||
}
|
||||
node.position = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !cbCount ) {
|
||||
cbCount++;
|
||||
cb();
|
||||
}
|
||||
},
|
||||
|
||||
stop : function() {
|
||||
this.oldNodes_ = this.nodes_;
|
||||
this.nodes_ = [];
|
||||
this.edges_ = [];
|
||||
},
|
||||
|
||||
addNode : function( nodeView ) {
|
||||
var node = new KIT.View.AnimationLayout.Node( nodeView, this );
|
||||
if ( this.oldNodes_.length ) {
|
||||
var oldNodes = this.oldNodes_.filter( function( n ) { return n.view === nodeView; } );
|
||||
if ( oldNodes.length ) {
|
||||
node.wasVisible = true;
|
||||
node.wasCenter = oldNodes[0].isCenter;
|
||||
}
|
||||
}
|
||||
this.nodes_.push( node );
|
||||
},
|
||||
|
||||
addEdge : function( edgeView ) {
|
||||
var from = this.nodes_.filter( function( n ) { return n.view === edgeView.from.lastParent; })[0];
|
||||
var to = this.nodes_.filter( function( n ) { return n.view === edgeView.to.lastParent; })[0];
|
||||
|
||||
if ( !from || !to ) {
|
||||
console.error( edgeView.model.name, from, to, 'Edge is not connected to nodes' );
|
||||
}
|
||||
|
||||
this.edges_.push( new KIT.View.AnimationLayout.Edge( edgeView, from, to, this ) );
|
||||
}
|
||||
|
||||
};
|
||||
@@ -0,0 +1,361 @@
|
||||
KIT.View.Class = function( model, program, parent ) {
|
||||
KIT.View.Node.call( this, model, program, parent );
|
||||
|
||||
this.nodeViews_ = [];
|
||||
|
||||
this.publics_ = [];
|
||||
this.privates_ = [];
|
||||
|
||||
for ( var i = 0; i < model.nodes.length; i++ ) {
|
||||
var node = model.nodes[i];
|
||||
var NodeViewType;
|
||||
|
||||
switch ( node.type ) {
|
||||
case KIT.Types.Class : NodeViewType = KIT.View.Class; break;
|
||||
case KIT.Types.Variable : NodeViewType = KIT.View.Variable; break;
|
||||
case KIT.Types.Member : NodeViewType = KIT.View.Member; break;
|
||||
case KIT.Types.Function : NodeViewType = KIT.View.Function; break;
|
||||
case KIT.Types.Method : NodeViewType = KIT.View.Method; break;
|
||||
|
||||
default: console.error( "Unknown node type!", node.type );
|
||||
}
|
||||
|
||||
var view = new NodeViewType( node, program, this );
|
||||
|
||||
if ( node.visibility === KIT.Visibility.Public ) {
|
||||
if ( parent && node.type === KIT.Types.Class ) {
|
||||
this.publics_.unshift( view );
|
||||
} else {
|
||||
this.publics_.push( view );
|
||||
}
|
||||
} else if ( node.visibility === KIT.Visibility.Private ) {
|
||||
if ( parent && node.type === KIT.Types.Class ) {
|
||||
this.privates_.unshift( view );
|
||||
} else {
|
||||
this.privates_.push( view );
|
||||
}
|
||||
}
|
||||
|
||||
if ( parent && node.type === KIT.Types.Class ) {
|
||||
this.nodeViews_.unshift( view );
|
||||
} else {
|
||||
this.nodeViews_.push( view );
|
||||
}
|
||||
}
|
||||
|
||||
this.open_ = false;
|
||||
this.publicOpen_ = false;
|
||||
this.privateOpen_ = false;
|
||||
}
|
||||
|
||||
KIT.View.Class.prototype = {
|
||||
__proto__ : KIT.View.Node.prototype,
|
||||
|
||||
get children() {
|
||||
return this.nodeViews_;
|
||||
},
|
||||
|
||||
get activeChildren() {
|
||||
var children = [];
|
||||
for ( var i = 0; i < this.nodeViews_.length; i++ ) {
|
||||
children = children.concat( this.nodeViews_[i].activeChildren );
|
||||
}
|
||||
if ( this.active ) {
|
||||
children.push( this );
|
||||
}
|
||||
return children;
|
||||
},
|
||||
|
||||
get nodeViews() {
|
||||
return this.nodeViews_;
|
||||
},
|
||||
|
||||
get invisibleEdgeCount() {
|
||||
var sum = 0;
|
||||
var nodes = this.nodeViews_;
|
||||
if ( nodes.length ) {
|
||||
var a = [];
|
||||
for ( var i = 0; i < nodes.length; i ++ ) {
|
||||
a = a.concat(nodes[i].invisibleEdges);
|
||||
}
|
||||
sum += a.unique().filter( function(e) {
|
||||
return e.from.lastParent !== e.to.lastParent;
|
||||
}).length;
|
||||
}
|
||||
|
||||
sum += this.edgeViews_.filter( function(e) {
|
||||
return !e.visible;
|
||||
}).length;
|
||||
|
||||
return sum;
|
||||
},
|
||||
|
||||
get openContent() {
|
||||
if ( !this.nodeViews.length ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var open = this.open_;
|
||||
return this.nodeViews_.filter( function( node ) {
|
||||
return open || node.visible;
|
||||
});
|
||||
},
|
||||
|
||||
get openPublics() {
|
||||
if ( !this.publics_.length ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var open = this.publicOpen_;
|
||||
return this.publics_.filter( function( node ) {
|
||||
return open || node.visible;
|
||||
});
|
||||
},
|
||||
|
||||
get openPrivates() {
|
||||
if ( !this.privates_.length ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
var open = this.privateOpen_;
|
||||
return this.privates_.filter( function( node ) {
|
||||
return open || node.visible;
|
||||
});
|
||||
},
|
||||
|
||||
toggle : function( e, key ) {
|
||||
if ( e.cancelBubble ) {
|
||||
return;
|
||||
}
|
||||
e.cancelBubble = true;
|
||||
|
||||
this[key] = !this[key];
|
||||
|
||||
this.setNeedsUpdate();
|
||||
},
|
||||
|
||||
init : function( paper ) {
|
||||
for ( var i = 0; i < this.nodeViews_.length; i++ ) {
|
||||
this.nodeViews_[i].init( paper );
|
||||
}
|
||||
|
||||
KIT.View.Node.prototype.init.call( this, paper );
|
||||
},
|
||||
|
||||
remove : function() {
|
||||
for ( var i = 0; i < this.nodeViews_.length; i++ ) {
|
||||
this.nodeViews_[i].remove();
|
||||
}
|
||||
|
||||
KIT.View.Node.prototype.remove.call( this );
|
||||
|
||||
if ( this.visibleCount_ === 0 && this.parent === KIT.Types.Program ) {
|
||||
this.open_ = false;
|
||||
this.publicOpen_ = false;
|
||||
this.privateOpen_ = false;
|
||||
}
|
||||
},
|
||||
|
||||
getNodeViewForModel : function( model ) {
|
||||
for ( var i = 0; i < this.nodeViews_.length; i++ ) {
|
||||
var nodeView = this.nodeViews_[i];
|
||||
if ( nodeView.model === model ) {
|
||||
return nodeView;
|
||||
} else if ( nodeView.model.type === KIT.Types.Class ) {
|
||||
nodeView = nodeView.getNodeViewForModel( model );
|
||||
if ( nodeView ) {
|
||||
return nodeView;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
getEdgeViewForModel : function( model ) {
|
||||
for ( var i = 0; i < this.edgeViews_.length; i++ ) {
|
||||
var edgeView = this.edgeView_[i];
|
||||
if ( edgeView.model === model ) {
|
||||
return edgeView;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
updateEdgeViews_ : function() {
|
||||
KIT.View.Node.prototype.updateEdgeViews_.call( this );
|
||||
|
||||
for ( var i = 0; i < this.nodeViews_.length; i++ ) {
|
||||
this.nodeViews_[i].updateEdgeViews_();
|
||||
}
|
||||
},
|
||||
|
||||
createShape : function( paper ) {
|
||||
var shape = paper.set();
|
||||
var box = { width : 0, y : 0, lines : [], cells : 1 };
|
||||
var bb, bb2;
|
||||
|
||||
var publics = this.openPublics;
|
||||
var privates = this.openPrivates;
|
||||
var content = this.openContent;
|
||||
|
||||
this.text = paper.text( 8, 10, this.model.shortName ).code( 18, this.textColor );
|
||||
bb = this.text.getBBox();
|
||||
this.text.translate( bb.width / 2, bb.height / 2 );
|
||||
shape.push( this.text );
|
||||
|
||||
box.y = bb.height + 15;
|
||||
box.width = bb.width;
|
||||
|
||||
if ( this.publics_.length || this.privates_.length ) {
|
||||
|
||||
box.cells= Math.max( Math.round( Math.sqrt( publics.length ) ),
|
||||
Math.round( Math.sqrt( privates.length ) ) );
|
||||
|
||||
var text;
|
||||
if ( this.publics_.length ) {
|
||||
text = paper.text( 35, box.y + 15, '+ public' ).code( 13, '#000' );
|
||||
box.width = Math.max( box.width, text.getBBox().width );
|
||||
box.lines.push( box.y );
|
||||
box.y += 30;
|
||||
|
||||
shape.push( text );
|
||||
|
||||
this.addContent( shape, paper, box, this.publics_.length, publics, 'publicOpen_' );
|
||||
}
|
||||
|
||||
if ( this.privates_.length ) {
|
||||
text = paper.text( 38, box.y + 15, '- private' ).code( 13, '#000' );
|
||||
box.width = Math.max( box.width, text.getBBox().width );
|
||||
box.lines.push( box.y );
|
||||
box.y += 30;
|
||||
|
||||
shape.push( text );
|
||||
|
||||
this.addContent( shape, paper, box, this.privates_.length, privates, 'privateOpen_' );
|
||||
}
|
||||
|
||||
} else if ( this.nodeViews_.length ) {
|
||||
box.lines.push( box.y );
|
||||
box.y += 10;
|
||||
|
||||
this.addContent( shape, paper, box, this.nodeViews_.length, content, 'open_' );
|
||||
}
|
||||
|
||||
box.width += 20;
|
||||
|
||||
if ( !this.active ) {
|
||||
this.number = paper.text( 0, 20, this.invisibleEdgeCount ).code( 14, this.textColor );
|
||||
bb2 = this.number.getBBox();
|
||||
if ( box.width < bb.width + 20 + bb2.width ) {
|
||||
this.number.translate( bb.width + bb2.width + 15 );
|
||||
box.width += bb2.width + 10;
|
||||
} else {
|
||||
this.number.translate( box.width - 10 - bb2.width / 2 );
|
||||
}
|
||||
shape.push( this.number );
|
||||
}
|
||||
|
||||
for ( var i = 0; i < box.lines.length; i++ ) {
|
||||
var y = box.lines[i] + 0.5;
|
||||
shape.push( paper.line( 0, y, box.width, y ).stroke( this.color, 1 ) );
|
||||
}
|
||||
|
||||
this.rect = paper.rect( 0, 0, box.width, box.y, 5 )
|
||||
this.rect.fill( this.backgroundColor );
|
||||
this.rect.toBack();
|
||||
|
||||
if ( this.model.abstraction === KIT.Abstraction.PureVirtual ) {
|
||||
this.rect.dash();
|
||||
}
|
||||
|
||||
shape.push( this.rect );
|
||||
return shape;
|
||||
},
|
||||
|
||||
addContent : function( shape, paper, box, length, content, key ) {
|
||||
if ( content.length ) {
|
||||
var startX = 7, x = startX;
|
||||
var gapX = 15, gapY = 10;
|
||||
var h = 0;
|
||||
var vec = new Vector;
|
||||
|
||||
for ( var i = 0; i < content.length; i++ ) {
|
||||
if ( i && i % box.cells === 0 ) {
|
||||
box.width = Math.max( box.width, x - gapX );
|
||||
x = startX;
|
||||
|
||||
box.y += h + gapY;
|
||||
h = 0;
|
||||
}
|
||||
|
||||
var node = content[i];
|
||||
node.add( true );
|
||||
node.dragable = false;
|
||||
|
||||
for ( var j = 0; j < node.shape.items.length; j++ ) {
|
||||
shape.push( node.shape.items[j] );
|
||||
}
|
||||
|
||||
var bb = node.bb;
|
||||
vec.set( x, box.y );
|
||||
node.position = vec;
|
||||
|
||||
h = Math.max( h, bb.height );
|
||||
x += bb.width + gapX;
|
||||
}
|
||||
|
||||
box.width = Math.max( box.width, x - gapX );
|
||||
box.y += h + gapY;
|
||||
}
|
||||
|
||||
var cb = this.updateAfterCallback( function(e) { this.toggle( e, key ); });
|
||||
var rect = paper.rect( 5, box.y - 7, 40, 20 ).fill( this.backgroundColor ).stroke();
|
||||
rect.click( cb, this );
|
||||
|
||||
var number = null;
|
||||
var point = { x : 20, y : box.y - 2, nx : 0, ny : 1 };
|
||||
if ( length > content.length ) {
|
||||
number = paper.text( 35, box.y + 3, length - content.length ).code( 13, this.textColor );
|
||||
number.click( cb, this );
|
||||
shape.push( number );
|
||||
|
||||
point.ny = -1;
|
||||
point.y += 8;
|
||||
}
|
||||
|
||||
var arrow = paper.arrow( point, 8, 6, true ).stroke( 'gray', 2 ).round();
|
||||
arrow.click( cb, this );
|
||||
shape.push( arrow );
|
||||
shape.push( rect );
|
||||
|
||||
var hoverIn = function() { arrow.stroke('black'); };
|
||||
var hoverOut = function() { arrow.stroke('gray'); };
|
||||
arrow.hover(hoverIn, hoverOut);
|
||||
rect.hover(hoverIn, hoverOut);
|
||||
if ( number ) number.hover(hoverIn, hoverOut);
|
||||
|
||||
box.y += 15;
|
||||
},
|
||||
|
||||
addViewsAtLocation : function( location, views ) {
|
||||
KIT.View.Node.prototype.addViewsAtLocation.call( this, location, views );
|
||||
|
||||
for ( var i = 0; i < this.children.length; i++ ) {
|
||||
this.children[i].addViewsAtLocation( location, views );
|
||||
}
|
||||
},
|
||||
|
||||
updateBB : function( vector ) {
|
||||
KIT.View.Node.prototype.updateBB.call( this, vector );
|
||||
|
||||
for ( var i = 0; i < this.children.length; i++ ) {
|
||||
this.children[i].updateBB( vector );
|
||||
}
|
||||
},
|
||||
|
||||
close : function() {
|
||||
this.open_ = false;
|
||||
this.publicOpen_ = false;
|
||||
this.privateOpen_ = false;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,372 @@
|
||||
KIT.View.Edge = function( model, program ) {
|
||||
KIT.View.View.call( this, model, program );
|
||||
|
||||
this.nodeViewFrom_ = null;
|
||||
this.nodeViewTo_ = null;
|
||||
|
||||
this.shapeThick_ = null;
|
||||
};
|
||||
|
||||
KIT.View.Edge.prototype = {
|
||||
__proto__ : KIT.View.View.prototype,
|
||||
|
||||
get color() {
|
||||
if ( this.highlighted ) {
|
||||
return '#48A65B';
|
||||
} else {
|
||||
return '#444';
|
||||
}
|
||||
},
|
||||
|
||||
hoverColor : '#48A65B',
|
||||
|
||||
get from() {
|
||||
return this.nodeViewFrom_;
|
||||
},
|
||||
|
||||
get to() {
|
||||
return this.nodeViewTo_;
|
||||
},
|
||||
|
||||
get visible() {
|
||||
return this.from.visible && this.to.visible && ( this.from.active || this.to.active || this.active );
|
||||
},
|
||||
|
||||
set clickable( enable ) {
|
||||
if ( !this.shape_ ) {
|
||||
console.error( 'has no shape' );
|
||||
}
|
||||
|
||||
if ( enable ) {
|
||||
this.shapeThick_.click( this.updateAfterCallback( this.click ), this );
|
||||
this.shape_.click( this.updateAfterCallback( this.click ), this );
|
||||
} else {
|
||||
this.shapeThick_.unclick();
|
||||
this.shape_.unclick();
|
||||
}
|
||||
},
|
||||
|
||||
set hoverable( enable ) {
|
||||
if ( !this.shape_ ) {
|
||||
console.error( 'has no shape' );
|
||||
}
|
||||
|
||||
if ( enable ) {
|
||||
this.shapeThick_.hover(
|
||||
this.updateAfterCallback( this.hoverIn ),
|
||||
this.updateAfterCallback( this.hoverOut ), this, this );
|
||||
this.shape_.hover(
|
||||
this.updateAfterCallback( this.hoverIn ),
|
||||
this.updateAfterCallback( this.hoverOut ), this, this );
|
||||
} else {
|
||||
this.shapeThick_.unhover();
|
||||
this.shape_.unhover();
|
||||
}
|
||||
},
|
||||
|
||||
init : function( paper, nodeViewFrom, nodeViewTo ) {
|
||||
this.paper_ = paper;
|
||||
this.nodeViewFrom_ = nodeViewFrom;
|
||||
this.nodeViewTo_ = nodeViewTo;
|
||||
|
||||
nodeViewFrom.addEdgeView( this );
|
||||
nodeViewTo.addEdgeView( this );
|
||||
},
|
||||
|
||||
remove : function() {
|
||||
if ( this.shape_ ) {
|
||||
this.shape_.remove();
|
||||
this.shapeThick_.remove();
|
||||
this.shape_ = null;
|
||||
this.shapeThick_ = null;
|
||||
|
||||
this.needsUpdate = false;
|
||||
}
|
||||
},
|
||||
|
||||
setNeedsUpdate : function() {
|
||||
this.needsUpdate = true;
|
||||
this.program.setNeedsEdgeUpdate();
|
||||
},
|
||||
|
||||
update : function() {
|
||||
if ( this.shape_ && this.needsUpdate ) {
|
||||
this.remove();
|
||||
this.add();
|
||||
this.needsUpdate = false;
|
||||
}
|
||||
},
|
||||
|
||||
add : function() {
|
||||
if ( !this.nodeViewFrom_.shape || !this.nodeViewTo_.shape ) {
|
||||
console.error( 'node has no shape' );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( this.shape_ ) {
|
||||
console.error( 'edge has already a shape' );
|
||||
}
|
||||
|
||||
this.shape_ = this.createShape( this.paper_, this.nodeViewFrom_, this.nodeViewTo_ );
|
||||
|
||||
if ( !this.shape_ ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.shapeThick_ = this.shape_.clone();
|
||||
this.shapeThick_.stroke( 'rgba(0,0,0,0)', 10 ).noDash();
|
||||
|
||||
if ( this.model.type !== KIT.Types.Aggregation ) {
|
||||
this.shapeThick_.toFront();
|
||||
this.shape_.toFront();
|
||||
} else {
|
||||
this.shapeThick_.toBack();
|
||||
this.shape_.toBack();
|
||||
}
|
||||
|
||||
if ( this.active ) {
|
||||
this.onActivate();
|
||||
} else {
|
||||
this.onDeactivate();
|
||||
}
|
||||
|
||||
this.clickable = true;
|
||||
this.hoverable = true;
|
||||
|
||||
this.needsUpdate = false;
|
||||
},
|
||||
|
||||
createShape : function( paper, nodeViewFrom, nodeViewTo ) {
|
||||
return paper.connection( nodeViewFrom.bb, nodeViewTo.bb, 'center', 'line' ).stroke( this.color, 2 );
|
||||
},
|
||||
|
||||
click : function( e ) {
|
||||
if ( e.cancelBubble ) {
|
||||
return;
|
||||
}
|
||||
e.cancelBubble = true;
|
||||
|
||||
this.program.activeView = this;
|
||||
},
|
||||
|
||||
activate : function() {
|
||||
this.active = true;
|
||||
this.highlighted = true;
|
||||
this.from.show();
|
||||
this.to.show();
|
||||
this.onActivate();
|
||||
},
|
||||
|
||||
deactivate : function() {
|
||||
this.active = false;
|
||||
this.highlighted = false;
|
||||
this.from.hide();
|
||||
this.to.hide();
|
||||
this.onDeactivate();
|
||||
},
|
||||
|
||||
onActivate : function() {
|
||||
if ( this.shape ) {
|
||||
this.shape.stroke( this.color );
|
||||
}
|
||||
},
|
||||
|
||||
onDeactivate : function() {
|
||||
if ( this.shape ) {
|
||||
this.shape.stroke( this.color );
|
||||
}
|
||||
},
|
||||
|
||||
hoverIn : function( e ) {
|
||||
if ( this.shape ) {
|
||||
this.shape.stroke( this.hoverColor );
|
||||
}
|
||||
},
|
||||
|
||||
hoverOut : function( e ) {
|
||||
if ( this.shape ) {
|
||||
this.shape.stroke( this.color );
|
||||
}
|
||||
},
|
||||
|
||||
showLocation : function() {
|
||||
if ( this.model.locations.length ) {
|
||||
KIT.FileViewer.showLocations( this.model.locations );
|
||||
}
|
||||
},
|
||||
|
||||
addLocation : function() {
|
||||
if ( this.model.locations.length ) {
|
||||
KIT.FileViewer.addLocations( this.model.locations );
|
||||
}
|
||||
},
|
||||
|
||||
addViewsAtLocation : function( location, views ) {
|
||||
if ( this.model.locations ) {
|
||||
for ( var i = 0; i < this.model.locations.length; i++ ) {
|
||||
if ( location.equals( this.model.locations[i] ) ) {
|
||||
views.push( this );
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// Derived views.
|
||||
|
||||
KIT.View.Aggregation = function( program ) {
|
||||
KIT.View.Edge.call( this, { type : KIT.Types.Aggregation }, program );
|
||||
|
||||
this.edgeViews_ = [];
|
||||
};
|
||||
|
||||
KIT.View.Aggregation.prototype = {
|
||||
__proto__ : KIT.View.Edge.prototype,
|
||||
|
||||
color : 'lightgray',
|
||||
hoverColor : 'gray',
|
||||
|
||||
get count() {
|
||||
return this.edgeViews_.length;
|
||||
},
|
||||
|
||||
show : function( edge ) {
|
||||
this.edgeViews_.push( edge );
|
||||
if ( this.count === 1 ) {
|
||||
this.from.show();
|
||||
this.to.show();
|
||||
}
|
||||
},
|
||||
|
||||
hide : function() {
|
||||
this.edgeViews_ = [];
|
||||
this.from.hide();
|
||||
this.to.hide();
|
||||
},
|
||||
|
||||
init : function( paper, nodeViewFrom, nodeViewTo ) {
|
||||
this.paper_ = paper;
|
||||
this.nodeViewFrom_ = nodeViewFrom;
|
||||
this.nodeViewTo_ = nodeViewTo;
|
||||
},
|
||||
|
||||
createShape : function( paper, nodeViewFrom, nodeViewTo ) {
|
||||
var shape = paper.set();
|
||||
var line = paper.connection( nodeViewFrom.bb, nodeViewTo.bb, 'center', 'line' )
|
||||
line.stroke( this.color, 3 + this.count );
|
||||
|
||||
var a = new Vector().copy( line.start );
|
||||
var b = new Vector().copy( line.end );
|
||||
|
||||
var bbA = nodeViewFrom.bb;
|
||||
var bbB = nodeViewTo.bb;
|
||||
|
||||
var u = b.sub( a ).normalizeSelf();
|
||||
var alpha = u.angle();
|
||||
var v = new Vector();
|
||||
var w = new Vector();
|
||||
|
||||
v.copy( u ).mulSelf( w.set( bbA.width / 2 * Math.cos( alpha ), bbA.height / 2 * Math.sin( alpha ) ).norm() );
|
||||
a.addSelf( v );
|
||||
|
||||
v.copy( u ).mulSelf( w.set( bbB.width / 2 * Math.cos( alpha ), bbB.height / 2 * Math.sin( alpha ) ).norm() * -1 );
|
||||
b.addSelf( v );
|
||||
|
||||
v.copy( a ).addSelf( b ).divSelf( 2 );
|
||||
|
||||
var circle = paper.circle( v.x, v.y - 1, 10 ).fill( 'white' ).stroke( 'black', 3 );
|
||||
var number = paper.text( v.x, v.y, this.count ).code( 12, 'black' );
|
||||
|
||||
shape.push( line, number, circle );
|
||||
return shape;
|
||||
},
|
||||
|
||||
click : function( e ) {
|
||||
if ( e.cancelBubble ) {
|
||||
return;
|
||||
}
|
||||
e.cancelBubble = true;
|
||||
|
||||
this.program.activeViews = this.edgeViews_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
KIT.View.Usage = function( model, program ) {
|
||||
KIT.View.Edge.call( this, model, program );
|
||||
};
|
||||
|
||||
KIT.View.Usage.prototype = {
|
||||
__proto__ : KIT.View.Edge.prototype,
|
||||
|
||||
// color : '#e26345',
|
||||
// hoverColor : '#FF7050',
|
||||
|
||||
createShape : function( paper, nodeViewFrom, nodeViewTo ) {
|
||||
var shape = paper.set();
|
||||
var line = paper.connection( nodeViewFrom.bb, nodeViewTo.bb, 'middle', 'line' );
|
||||
var arrow = paper.arrow( line.end, 6, 3, true ).fill( this.color );
|
||||
shape.push( line, arrow );
|
||||
shape.stroke( this.color, 1 );
|
||||
return shape;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
KIT.View.Call = function( model, program ) {
|
||||
KIT.View.Edge.call( this, model, program );
|
||||
};
|
||||
|
||||
KIT.View.Call.prototype = {
|
||||
__proto__ : KIT.View.Edge.prototype,
|
||||
|
||||
// color : '#6295b2',
|
||||
// hoverColor : '#7BBADE',
|
||||
|
||||
createShape : function( paper, nodeViewFrom, nodeViewTo ) {
|
||||
var shape = paper.set();
|
||||
var line = paper.connection( nodeViewFrom.bb, nodeViewTo.bb, 'middle', 'wave' );
|
||||
var arrow = paper.arrow( line.end, 10, 5, false );
|
||||
shape.push( line, arrow );
|
||||
shape.stroke( this.color, 1 );
|
||||
|
||||
if ( this.model.abstraction === KIT.Abstraction.PureVirtual ) {
|
||||
line.dash();
|
||||
}
|
||||
|
||||
return shape;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
KIT.View.Inheritance = function( model, program ) {
|
||||
KIT.View.Edge.call( this, model, program );
|
||||
};
|
||||
|
||||
KIT.View.Inheritance.prototype = {
|
||||
__proto__ : KIT.View.Edge.prototype,
|
||||
|
||||
createShape : function( paper, nodeViewFrom, nodeViewTo ) {
|
||||
var shape = paper.set();
|
||||
var line = paper.connection( nodeViewTo.bb, nodeViewFrom.bb, 'middle', 'line' );
|
||||
var arrow = paper.arrow( line.end, 20, 10, true ).fill( 'white' );
|
||||
shape.push( line, arrow );
|
||||
shape.stroke( this.color, 2 );
|
||||
return shape;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
KIT.View.Instantiation = function( model, program ) {
|
||||
KIT.View.Edge.call( this, model, program );
|
||||
};
|
||||
|
||||
KIT.View.Instantiation.prototype = {
|
||||
__proto__ : KIT.View.Edge.prototype,
|
||||
|
||||
createShape : function( paper, nodeViewFrom, nodeViewTo ) {
|
||||
return paper.connection( nodeViewFrom.bb, nodeViewTo.bb, 'middle', 'line' ).stroke( this.color, 2 ).dash();
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,203 @@
|
||||
KIT.View.ForceLayout = function( program, center ) {
|
||||
this.program_ = program;
|
||||
this.center_ = center;
|
||||
|
||||
this.nodes_ = [];
|
||||
this.edges_ = [];
|
||||
|
||||
this.time_ = null;
|
||||
};
|
||||
|
||||
KIT.View.ForceLayout.Node = function( nodeView, layout ) {
|
||||
this.view = nodeView.lastParent;
|
||||
this.active = !!nodeView.activeChildren.length;
|
||||
this.layout_ = layout;
|
||||
|
||||
this.move = new Vector();
|
||||
this.velocity = new Vector;
|
||||
this.force = new Vector;
|
||||
|
||||
this.dt = 0;
|
||||
};
|
||||
|
||||
KIT.View.ForceLayout.Node.prototype = {
|
||||
|
||||
mass : 3,
|
||||
damp : 0.5,
|
||||
|
||||
vector : new Vector,
|
||||
acceleration : new Vector,
|
||||
|
||||
get position() {
|
||||
return this.view.center;
|
||||
},
|
||||
|
||||
start : function() {
|
||||
this.view.update();
|
||||
},
|
||||
|
||||
update : function( dt ) {
|
||||
this.dt += dt;
|
||||
|
||||
this.view.updateEdgeViews_();
|
||||
|
||||
this.force.clampSelf( 2000 );
|
||||
|
||||
this.acceleration.copy( this.force ).mulSelf( 1 / this.mass );
|
||||
this.force.set( 0, 0 );
|
||||
|
||||
if ( this.active ) {
|
||||
this.view.moveBy( this.layout_.center_.sub( this.view.center ).mulSelf( 0.1 ) );
|
||||
return;
|
||||
} else if ( this.view.isDragging ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.velocity.addSelf( this.acceleration.mulSelf( dt ) );
|
||||
|
||||
this.move.set( 0, 0 );
|
||||
this.move.addSelf( this.acceleration.mulSelf( dt * this.damp ) );
|
||||
this.move.addSelf( this.acceleration.copy( this.velocity ).mulSelf( dt ) );
|
||||
|
||||
this.velocity.mulSelf( 0.97 );
|
||||
|
||||
if ( this.move.normSquared() > 0.001 ) {
|
||||
this.view.moveBy( this.move );
|
||||
}
|
||||
},
|
||||
|
||||
reset : function() {
|
||||
this.velocity.set( 0, 0 );
|
||||
this.force.set( 0, 0 );
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
KIT.View.ForceLayout.Edge = function( edgeView, from, to, layout ) {
|
||||
this.views = [edgeView];
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.layout_ = layout;
|
||||
|
||||
this.length = 0;
|
||||
this.nominalLength = 200;
|
||||
|
||||
this.dt = 0;
|
||||
};
|
||||
|
||||
KIT.View.ForceLayout.Edge.prototype = {
|
||||
|
||||
strength : 10,
|
||||
vector : new Vector,
|
||||
|
||||
start : function() {
|
||||
this.views.forEach( function(v) { v.add(); } );
|
||||
},
|
||||
|
||||
update : function( dt ) {
|
||||
this.dt += dt;
|
||||
|
||||
this.vector.copy( this.from.position ).subSelf( this.to.position )
|
||||
|
||||
this.length = this.vector.norm();
|
||||
this.vector.normalizeSelf().mulSelf( this.strength * ( this.length - this.nominalLength ) );
|
||||
|
||||
this.to.force.addSelf( this.vector );
|
||||
this.from.force.addSelf( this.vector.mulSelf( -1 ) );
|
||||
}
|
||||
};
|
||||
|
||||
KIT.View.ForceLayout.prototype = {
|
||||
|
||||
stop : function() {
|
||||
this.time_ = null;
|
||||
this.nodes_ = [];
|
||||
this.edges_ = [];
|
||||
},
|
||||
|
||||
start : function() {
|
||||
if ( this.time_ ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.time_ = Date.now();
|
||||
|
||||
this.nodes_.forEach( function( n ) { n.start(); });
|
||||
this.edges_.forEach( function( e ) { e.start(); });
|
||||
|
||||
requestAnimationFrame( bind( this, this.tick ) );
|
||||
},
|
||||
|
||||
tick : function( dt ) {
|
||||
if ( this.time_ ) {
|
||||
requestAnimationFrame( bind( this, this.tick ) );
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
var t = Date.now();
|
||||
var dt = ( t - this.time_ ) / 1000;
|
||||
|
||||
this.time_ = t;
|
||||
|
||||
this.update( dt );
|
||||
this.program_.update();
|
||||
},
|
||||
|
||||
update : function( dt ) {
|
||||
this.edges_.forEach( function( e ) { e.update( dt ); });
|
||||
|
||||
var vector = new Vector;
|
||||
for ( var i = 0; i < this.nodes_.length; i++ ) {
|
||||
var a = this.nodes_[i];
|
||||
for ( var j = i + 1; j < this.nodes_.length; j++ ) {
|
||||
var b = this.nodes_[j];
|
||||
|
||||
vector.copy( a.view.center ).subSelf( b.view.center );
|
||||
if ( vector.normSquared() > 200 * 200 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var push = true;
|
||||
// for ( var k = 0; k < this.edges_.length; k++ ) {
|
||||
// var from = this.edges_[k].from;
|
||||
// var to = this.edges_[k].to;
|
||||
// if ( ( from === a && to === b ) || ( from === b && to === a ) ) {
|
||||
// push = false;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
if ( push ) {
|
||||
var norm = vector.norm();
|
||||
vector.mulSelf( ( 200 - norm ) / norm * 30 );
|
||||
a.force.addSelf( vector );
|
||||
b.force.addSelf( vector.mulSelf( -1 ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.nodes_.forEach( function( n ) { n.update( dt ); });
|
||||
},
|
||||
|
||||
addNode : function( nodeView ) {
|
||||
this.nodes_.push( new KIT.View.ForceLayout.Node( nodeView, this ) );
|
||||
},
|
||||
|
||||
addEdge : function( edgeView ) {
|
||||
var from = this.nodes_.filter( function( n ) { return n.view === edgeView.from.lastParent; })[0];
|
||||
var to = this.nodes_.filter( function( n ) { return n.view === edgeView.to.lastParent; })[0];
|
||||
|
||||
if ( !from || !to ) {
|
||||
console.error( edgeView.model.name, from, to, 'Edge is not connected to nodes' );
|
||||
}
|
||||
|
||||
var oldEdge = this.edges_.filter( function( e ) { return e.from === from && e.to === to; });
|
||||
if ( oldEdge.length ) {
|
||||
oldEdge[0].views.push( edgeView );
|
||||
} else {
|
||||
this.edges_.push( new KIT.View.ForceLayout.Edge( edgeView, from, to, this ) );
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||