Merge: Copy to native
authorJean Privat <jean@pryen.org>
Thu, 14 May 2015 12:52:38 +0000 (08:52 -0400)
committerJean Privat <jean@pryen.org>
Thu, 14 May 2015 12:52:38 +0000 (08:52 -0400)
Added copy_to_native method in Text, also its optimized versions for subclasses

As a bonus (and because it simplified my task here), substrings now return FlatTexts only instead of simple Text.

The latter will permit the implementation of StringReader as BufferedReader later in an optimized way

Pull-Request: #1335
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Jean Privat <jean@pryen.org>

35 files changed:
examples/mnit_simple/src/complete_simple_android.nit
examples/mnit_simple/src/test_target_api.nit
lib/android/android.nit
lib/android/aware.nit
lib/android/intent/intent_api11.nit
lib/android/intent/intent_api12.nit
lib/android/intent/intent_api14.nit
lib/android/intent/intent_api15.nit
lib/android/intent/intent_api16.nit
lib/android/intent/intent_api17.nit
lib/android/intent/intent_api18.nit
lib/android/intent/intent_api19.nit
lib/android/log.nit
lib/android/notification/native_notification.nit
lib/android/shared_preferences/shared_preferences_api11.nit
lib/android/ui/native_ui.nit
lib/app/app_base.nit
lib/io/io.nit [deleted file]
lib/io/push_back_reader.nit [deleted file]
lib/io/test_push_back_reader.nit [deleted file]
lib/linux/data_store.nit
lib/mnit/assets.nit
lib/mnit_linux/linux_assets.nit
lib/standard/file.nit
lib/standard/stream.nit
share/nitdoc/css/nitdoc.css
src/doc/doc_phases/doc_graphs.nit
src/doc/doc_phases/doc_hierarchies.nit
src/doc/doc_phases/doc_intros_redefs.nit
src/doc/doc_phases/doc_structure.nit
src/doc/html_templates/html_components.nit
src/doc/html_templates/html_templates.nit
src/platform/android_annotations.nit
tests/sav/test_peek.res [new file with mode: 0644]
tests/test_peek.nit [new file with mode: 0644]

index f8cff4f..68f3a85 100644 (file)
@@ -16,7 +16,7 @@
 
 module complete_simple_android is
        app_namespace "org.nitlanguage.test_all"
-       target_api_version 19
+       android_api_target 19
 end
 
 import test_bundle
index 6a2503a..3992c09 100644 (file)
@@ -16,8 +16,8 @@
 
 # Test for the API level related annotations
 module test_target_api is
-       min_api_version(10)
-       max_api_version(19)
+       android_api_min 10
+       android_api_max 19
 end
 
 import simple_android
index 6c6fb9b..42f3471 100644 (file)
@@ -26,14 +26,7 @@ import dalvik
 private import log
 private import data_store
 
-# Uses Android logs to print everything
-redef fun print(text) do log_write(priority_info, app.log_prefix.to_cstring, text.to_s.to_cstring)
-
 redef class App
-       redef fun log_error(msg) do log_write(priority_error, log_prefix.to_cstring, msg.to_cstring)
-
-       redef fun log_warning(msg) do log_write(priority_warn, log_prefix.to_cstring, msg.to_cstring)
-
        redef fun init_window
        do
                super
index fec387d..0257dc8 100644 (file)
 
 # Android compatibility module
 #
-# Defines all Android related annoations including the `@android` annotations
-# used to tag `ldflags` annotations.
+# Defines all Android related annotations, including `ldflags@android`.
 module aware is
        new_annotation android
-       new_annotation min_api_version
-       new_annotation max_api_version
-       new_annotation target_api_version
+       new_annotation android_api_min
+       new_annotation android_api_max
+       new_annotation android_api_target
        new_annotation android_manifest
        new_annotation android_manifest_application
        new_annotation android_manifest_activity
index 1ba5e88..db0415a 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Refines intent module to add API 11 services
-module intent_api11 is min_api_version(11)
+module intent_api11 is android_api_min 11
 
 import intent
 
index ddf2cff..9af4402 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Refines intent module to add API 12 services
-module intent_api12 is min_api_version(12)
+module intent_api12 is android_api_min 12
 
 import intent_api11
 
index 3bb6576..dc323d2 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Refines intent module to add API 14 services
-module intent_api14 is min_api_version(14)
+module intent_api14 is android_api_min 14
 
 import intent_api12
 
index 4df53ce..cab60aa 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Refines intent module to add API 15 services
-module intent_api15 is min_api_version(15)
+module intent_api15 is android_api_min 15
 
 import intent_api14
 
index 74f6b0a..1513ab8 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Refines intent module to add API 16 services
-module intent_api16 is min_api_version(16)
+module intent_api16 is android_api_min 16
 
 import intent_api15
 
index 0299a21..1d92cdc 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Refines intent module to add API 17 services
-module intent_api17 is min_api_version(17)
+module intent_api17 is android_api_min 17
 
 import intent_api16
 
index 840bceb..b348b3d 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Refines intent module to add API 18 services
-module intent_api18 is min_api_version(18)
+module intent_api18 is android_api_min 18
 
 import intent_api17
 
index 73b1d8b..08af94a 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Refines intent module to add API 19 services
-module intent_api19 is min_api_version(19)
+module intent_api19 is android_api_min 19
 
 import intent_api18
 
index 6b0faea..b7f7e64 100644 (file)
@@ -23,31 +23,54 @@ in "C" `{
        #include <android/log.h>
 `}
 
+# Use Android logs to print
+redef fun print(object)
+do
+       log_write(priority_info, app.log_prefix.to_cstring, object.to_s.to_cstring)
+end
+
+# Use Android logs to print errors
+redef fun print_error(object)
+do
+       log_write(priority_error, app.log_prefix.to_cstring, object.to_s.to_cstring)
+end
+
+# Use Android logs to print warnings
+redef fun print_warning(object)
+do
+       log_write(priority_warn, app.log_prefix.to_cstring, object.to_s.to_cstring)
+end
+
+redef class App
+       # Prefix to all log messages
+       protected fun log_prefix: String do return "app.nit"
+end
+
 # Default Android log priority
-fun priority_default: Int do return 1
+private fun priority_default: Int do return 1
 
 # Verbose Android log priority
-fun priority_verbose: Int do return 2
+private fun priority_verbose: Int do return 2
 
 # Debug Android log priority
-fun priority_debug: Int do return 3
+private fun priority_debug: Int do return 3
 
 # Info Android log priority
-fun priority_info: Int do return 4
+private fun priority_info: Int do return 4
 
 # Warn Android log priority
-fun priority_warn: Int do return 5
+private fun priority_warn: Int do return 5
 
 # Error Android log priority
-fun priority_error: Int do return 6
+private fun priority_error: Int do return 6
 
 # Fatal Android log priority
-fun priority_fatal: Int do return 7
+private fun priority_fatal: Int do return 7
 
 # Silent Android log priority
-fun priority_silent: Int do return 8
+private fun priority_silent: Int do return 8
 
 # Write `text` to Android log at priority `level` with tag `tag`
-fun log_write(level: Int, tag, text: NativeString) `{
+private fun log_write(level: Int, tag, text: NativeString) `{
        __android_log_write(level, tag, text);
 `}
index 988727f..82c873f 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Native Java classes for notifications
-module native_notification is min_api_version 11
+module native_notification is android_api_min 11
 
 import android::assets_and_resources
 
index cb55acc..48d600a 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Refines shared_preferences module to add API 11 services
-module shared_preferences_api11 is min_api_version(11)
+module shared_preferences_api11 is android_api_min 11
 
 import shared_preferences
 
index bd008c1..79b75a5 100644 (file)
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 # Native services from the `android.view` and `android.widget` namespaces
-module native_ui is min_api_version 14
+module native_ui is android_api_min 14
 
 import nit_activity
 
index 2a335c4..76fbd09 100644 (file)
@@ -34,15 +34,6 @@ class App
        # Main entry point of your application
        fun run do end
 
-       # Prefix to all log messages, used by `log_error`, `log_warning` and `log_info`.
-       fun log_prefix: String do return "app.nit"
-
-       # Helper function for logging errors
-       fun log_error(msg: String) do sys.stderr.write "{log_prefix} error: {msg}\n"
-
-       # Helper function for logging warnings
-       fun log_warning(msg: String) do sys.stderr.write "{log_prefix} warn: {msg}\n"
-
        # Main init method for graphical stuff
        # Is called when display is ready so graphical assets
        # can be loaded at this time.
@@ -52,6 +43,14 @@ class App
        fun window_closing do end
 end
 
+# Print a warning
+fun print_warning(object: Object)
+do
+       sys.stderr.write object.to_s
+       sys.stderr.write "\n"
+end
+
+# The running `App`
 fun app: App do return once new App
 app.setup
 app.run
diff --git a/lib/io/io.nit b/lib/io/io.nit
deleted file mode 100644 (file)
index c48b171..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# This file is free software, which comes along with NIT. This software is
-# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE. You can modify it is you want, provided this header
-# is kept unaltered, and a notification of the changes is added.
-# You are allowed to redistribute it and sell it, alone or is a part of
-# another product.
-
-# Additional services for streams.
-module io
-
-import push_back_reader
diff --git a/lib/io/push_back_reader.nit b/lib/io/push_back_reader.nit
deleted file mode 100644 (file)
index 2fa2d19..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# This file is free software, which comes along with NIT. This software is
-# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE. You can modify it is you want, provided this header
-# is kept unaltered, and a notification of the changes is added.
-# You are allowed to redistribute it and sell it, alone or is a part of
-# another product.
-
-# Input stream that permits to push bytes back to the stream.
-module io::push_back_reader
-
-# Input stream that permits to push bytes back to the stream.
-class PushBackReader
-       super Reader
-
-       # Push the specified byte back to the stream.
-       #
-       # The specified byte is usually the last read byte that is not
-       # “unread” already.
-       fun unread_char(c: Char) is abstract
-
-       # Push the specified string back to the stream.
-       #
-       # The specified string is usually the last read string that is not
-       # “unread” already.
-       fun unread(s: String) do
-               for c in s.chars.reverse_iterator do unread_char(c)
-       end
-end
-
-# Decorates an input stream to permit to push bytes back to the input stream.
-class PushBackDecorator
-       super PushBackReader
-
-       # The parent stream.
-       var parent: Reader
-
-       # The stack of the pushed-back bytes.
-       #
-       # Bytes are in the reverse order they will reappear in the stream.
-       # `unread` pushes bytes after already pushed-back bytes.
-       #
-       # TODO: With optimized bulk array copy operations, a reversed stack (like in
-       # OpenJDK) would be more efficient.
-       private var buf: Sequence[Char] = new Array[Char]
-
-       redef fun read_char: Int do
-               if buf.length <= 0 then return parent.read_char
-               return buf.pop.ascii
-       end
-
-       redef fun read(i: Int): String do
-               if i <= 0 then return ""
-               if buf.length <= 0 then return parent.read(i)
-               var s = new FlatBuffer.with_capacity(i)
-
-               loop
-                       s.chars.push(buf.pop)
-                       i -= 1
-                       if i <= 0 then
-                               return s.to_s
-                       else if buf.length <= 0 then
-                               s.append(parent.read(i))
-                               return s.to_s
-                       end
-               end
-       end
-
-       redef fun read_all: String do
-               if buf.length <= 0 then return parent.read_all
-               var s = new FlatBuffer
-
-               loop
-                       s.chars.push(buf.pop)
-                       if buf.length <= 0 then
-                               s.append(parent.read_all)
-                               return s.to_s
-                       end
-               end
-       end
-
-       redef fun append_line_to(s: Buffer) do
-               if buf.length > 0 then
-                       var c: Char
-
-                       loop
-                               c = buf.pop
-                               s.chars.push(c)
-                               if c == '\n' then return
-                               if buf.length <= 0 then break
-                       end
-               end
-               parent.append_line_to(s)
-       end
-
-       redef fun eof: Bool do return buf.length <= 0 and parent.eof
-
-       redef fun close do
-               buf.clear
-               parent.close
-       end
-
-       redef fun unread_char(c: Char) do buf.push(c)
-
-       redef fun unread(s: String) do
-               for c in s.chars.reverse_iterator do buf.push(c)
-       end
-end
diff --git a/lib/io/test_push_back_reader.nit b/lib/io/test_push_back_reader.nit
deleted file mode 100644 (file)
index 1498ccf..0000000
+++ /dev/null
@@ -1,158 +0,0 @@
-# This file is part of NIT ( http://www.nitlanguage.org ).
-#
-# This file is free software, which comes along with NIT. This software is
-# distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
-# without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-# PARTICULAR PURPOSE. You can modify it is you want, provided this header
-# is kept unaltered, and a notification of the changes is added.
-# You are allowed to redistribute it and sell it, alone or is a part of
-# another product.
-
-# Test suites for module `push_back_reader`
-module test_push_back_reader is test_suite
-
-import test_suite
-import io::push_back_reader
-
-class TestPushBackDecorator
-       super TestSuite
-
-       private fun sample: PushBackDecorator do
-               return new PushBackDecorator(new StringReader("""
-abcd
-
-efg
-"""))
-       end
-
-       fun test_read_char do
-               var subject = sample
-
-               assert 'a' == subject.read_char.ascii
-       end
-
-       fun test_read_char_eof do
-               var subject = new PushBackDecorator(new StringReader(""))
-
-               assert -1 == subject.read_char
-       end
-
-       fun test_unread_read_char do
-               var subject = sample
-
-               subject.unread_char('z')
-               assert 'z' == subject.read_char.ascii
-               assert 'a' == subject.read_char.ascii
-       end
-
-       fun test_read_partial do
-               var subject = sample
-
-               assert "abcd" == subject.read(4)
-       end
-
-       fun test_read_too_much do
-               var subject = sample
-               var exp = """
-abcd
-
-efg
-"""
-               assert exp == subject.read(100)
-       end
-
-       fun test_unread_read do
-               var subject = sample
-
-               subject.unread("a")
-               assert "aab" == subject.read(3)
-       end
-
-       fun test_unread_read_mixed do
-               var subject = sample
-
-               subject.unread("a")
-               assert "aab" == subject.read(3)
-       end
-
-       fun test_read_all do
-               var subject = sample
-               var exp = """
-abcd
-
-efg
-"""
-               assert exp == subject.read_all
-       end
-
-       fun test_unread_read_all do
-               var subject = sample
-               var exp = """
-fooabcd
-
-efg
-"""
-               subject.unread("foo")
-               assert exp == subject.read_all
-       end
-
-       fun test_read_line do
-               var subject = sample
-
-               assert "abcd" == subject.read_line
-               assert "" == subject.read_line
-       end
-
-       fun test_unread_read_line do
-               var subject = sample
-
-               subject.unread("a\nb")
-               assert "a" == subject.read_line
-               assert "babcd" == subject.read_line
-       end
-
-       fun test_eof do
-               var subject = sample
-
-               assert not subject.eof
-               subject.read_all
-               assert subject.eof
-       end
-
-       fun test_eof_empty do
-               var subject = new PushBackDecorator(new StringReader(""))
-
-               assert subject.eof
-       end
-
-       fun test_close do
-               var subject = sample
-
-               subject.close
-               assert subject.eof
-       end
-
-       fun test_unread_close do
-               var subject = sample
-
-               subject.unread("foo")
-               subject.close
-               assert subject.eof
-       end
-
-       fun test_unread_char_order do
-               var subject = sample
-
-               subject.unread_char('z')
-               subject.unread_char('y')
-               assert "yzab" == subject.read(4)
-       end
-
-       fun test_unread_order do
-               var subject = sample
-
-               subject.unread("bar")
-               subject.unread("foo")
-               assert "foobarab" == subject.read(8)
-       end
-end
index 3a017dc..5743d82 100644 (file)
@@ -52,7 +52,7 @@ private class LinuxStore
                # Open DB connection
                db = new Sqlite3DB.open(db_path)
                if not db.is_open then
-                       app.log_error "Data store unavaible, cannot load/save data. (at '{db_path}' with '{db.error or else "unknown"}')"
+                       print_error "Data store unavaible, cannot load/save data. (at '{db_path}' with '{db.error or else "unknown"}')"
                        return null
                end
 
index f0d1892..d46b5e4 100644 (file)
@@ -42,7 +42,7 @@ redef class App
        do
                var asset = try_loading_asset( id )
                if asset == null then # error
-                       log_error( "asset <{id}> could not be loaded." )
+                       print_error "asset <{id}> could not be loaded."
                        abort
                else
                        return asset
@@ -57,7 +57,7 @@ redef class App
                if asset isa Image then
                        return asset
                else
-                       log_error( "asset <{id}> is not an image." )
+                       print_error "asset <{id}> is not an image."
                        abort
                end
        end
index 6749d30..393b77d 100644 (file)
@@ -33,7 +33,7 @@ redef class App
        do
                var path = "{assets_dir}/{id}"
                if not path.file_exists then
-                       log_error( "asset <{id}> does not exists." )
+                       print_error "asset <{id}> does not exists."
                        exit(1)
                        abort
                else
index bb87a6f..68853e1 100644 (file)
@@ -1214,6 +1214,13 @@ do
        sys.stdout.write("\n")
 end
 
+# Print `object` on the error output (`stderr` or a log system)
+fun print_error(object: Object)
+do
+       sys.stderr.write object.to_s
+       sys.stderr.write "\n"
+end
+
 # Read a character from the standard input (`stdin`).
 fun getc: Char
 do
index e0d3a67..4ad6af1 100644 (file)
@@ -392,6 +392,34 @@ abstract class BufferedReader
                return c.ascii
        end
 
+       # Peeks up to `n` bytes in the buffer, returns an empty string on EOF
+       #
+       # The operation does not consume the buffer
+       #
+       # ~~~nitish
+       #       var x = new FileReader("File.txt")
+       #       assert x.peek(5) == x.read(5)
+       # ~~~
+       fun peek(i: Int): String do
+               if eof then return ""
+               var b = new FlatBuffer.with_capacity(i)
+               while i > 0 and not eof do
+                       b.add _buffer[_buffer_pos]
+                       _buffer_pos += 1
+                       i -= 1
+               end
+               var nbuflen = b.length + (_buffer.length - _buffer_pos)
+               var nbuf = new FlatBuffer.with_capacity(nbuflen)
+               nbuf.append(b)
+               while _buffer_pos < _buffer.length do
+                       nbuf.add(_buffer[_buffer_pos])
+                       _buffer_pos += 1
+               end
+               _buffer_pos = 0
+               _buffer = nbuf
+               return b.to_s
+       end
+
        redef fun read(i)
        do
                if last_error != null then return ""
index 41a10b4..e47f3aa 100644 (file)
@@ -197,6 +197,20 @@ article.nospace {
        border-left: 2px solid #0d8921;
 }
 
+
+.pull-right .dropdown-toggle {
+       padding: 0 5px;
+}
+
+/* Hide the "..." link */
+
+article .dropdown, article .dropdown {
+       visibility: hidden;
+}
+article:hover .dropdown, article:target .dropdown {
+       visibility: visible;
+}
+
 /*
  * Page parts
  */
@@ -273,20 +287,6 @@ article.nospace {
        margin-left: 30px;
 }
 
-.source-link {
-       display: none;
-       float: right;
-       margin-top: 10px;
-}
-
-.source-link a {
-       color: #0d8921;
-}
-
-article:hover .source-link, article:target .source-link {
-       display: block;
-}
-
 /*
  * Code Highlighting
  */
index 0a011e8..07b7c99 100644 (file)
@@ -126,4 +126,6 @@ class GraphArticle
 
        # Dot script of the graph.
        var dot: Text
+
+       redef var is_empty = false
 end
index 23da906..5bfbfb1 100644 (file)
@@ -41,12 +41,14 @@ end
 redef class MModulePage
        redef fun build_inh_list(v, doc) do
                var section = new ImportationListSection(mentity)
+               var group = new PanelGroup("List")
                var imports = self.imports.to_a
                v.name_sorter.sort(imports)
-               section.add_child new HierarchyListArticle(mentity, "Imports", imports)
+               group.add_child new HierarchyListArticle(mentity, "Imports", imports)
                var clients = self.clients.to_a
                v.name_sorter.sort(clients)
-               section.add_child new HierarchyListArticle(mentity, "Clients", clients)
+               group.add_child new HierarchyListArticle(mentity, "Clients", clients)
+               section.add_child group
                section.parent = root.children.first
                root.children.first.children.insert(section, 1)
        end
@@ -55,18 +57,20 @@ end
 redef class MClassPage
        redef fun build_inh_list(v, doc) do
                var section = new InheritanceListSection(mentity)
+               var group = new PanelGroup("List")
                var parents = self.parents.to_a
                v.name_sorter.sort(parents)
-               section.add_child new HierarchyListArticle(mentity, "Parents", parents)
+               group.add_child new HierarchyListArticle(mentity, "Parents", parents)
                var ancestors = self.ancestors.to_a
                v.name_sorter.sort(ancestors)
-               section.add_child new HierarchyListArticle(mentity, "Ancestors", ancestors)
+               group.add_child new HierarchyListArticle(mentity, "Ancestors", ancestors)
                var children = self.children.to_a
                v.name_sorter.sort(children)
-               section.add_child new HierarchyListArticle(mentity, "Children", children)
+               group.add_child new HierarchyListArticle(mentity, "Children", children)
                var descendants = self.descendants.to_a
                v.name_sorter.sort(descendants)
-               section.add_child new HierarchyListArticle(mentity, "Descendants", descendants)
+               group.add_child new HierarchyListArticle(mentity, "Descendants", descendants)
+               section.add_child group
                section.parent = root.children.first
                root.children.first.children.insert(section, 1)
        end
@@ -74,13 +78,13 @@ end
 
 # FIXME diff hack
 class ImportationListSection
-       super DocSection
+       super TabbedGroup
        super MEntityComposite
 end
 
 # FIXME diff hack
 class InheritanceListSection
-       super DocSection
+       super TabbedGroup
        super MEntityComposite
 end
 
index afd8e55..54f7c18 100644 (file)
@@ -54,28 +54,42 @@ redef class DefinitionArticle
 
        # TODO this should move to MEntity?
        private fun build_mmodule_list(v: IntroRedefListPhase, doc: DocModel, mmodule: MModule) do
+               var section = new IntrosRedefsSection(mentity)
+               var group = new PanelGroup("List")
                var intros = mmodule.intro_mclassdefs(v.ctx.min_visibility).to_a
                doc.mainmodule.linearize_mclassdefs(intros)
-               add_child new IntrosRedefsListArticle(mentity, "Introduces", intros)
+               group.add_child new IntrosRedefsListArticle(mentity, "Introduces", intros)
                var redefs = mmodule.redef_mclassdefs(v.ctx.min_visibility).to_a
                doc.mainmodule.linearize_mclassdefs(redefs)
-               add_child new IntrosRedefsListArticle(mentity, "Redefines", redefs)
+               group.add_child new IntrosRedefsListArticle(mentity, "Redefines", redefs)
+               section.add_child group
+               add_child(section)
        end
 
        # TODO this should move to MEntity?
        private fun build_mclassdef_list(v: IntroRedefListPhase, doc: DocModel, mclassdef: MClassDef) do
+               var section = new IntrosRedefsSection(mentity)
+               var group = new PanelGroup("List")
                var intros = mclassdef.collect_intro_mpropdefs(v.ctx.min_visibility).to_a
                # FIXME avoid diff changes
                # v.ctx.mainmodule.linearize_mpropdefs(intros)
-               add_child new IntrosRedefsListArticle(mentity, "Introduces", intros)
+               group.add_child new IntrosRedefsListArticle(mentity, "Introduces", intros)
                var redefs = mclassdef.collect_redef_mpropdefs(v.ctx.min_visibility).to_a
                # FIXME avoid diff changes
                # v.ctx.mainmodule.linearize_mpropdefs(redefs)
-               add_child new IntrosRedefsListArticle(mentity, "Redefines", redefs)
+               group.add_child new IntrosRedefsListArticle(mentity, "Redefines", redefs)
+               section.add_child group
+               add_child(section)
        end
 
 end
 
+# Section that contains the intros and redefs lists.
+class IntrosRedefsSection
+       super TabbedGroup
+       super MEntitySection
+end
+
 # An article that displays a list of introduced / refined mentities.
 #
 # FIXME diff hack
index fc2dc17..d392961 100644 (file)
@@ -266,6 +266,21 @@ redef class MPropertyPage
        end
 end
 
+# A group of sections that can be displayed together in a tab.
+#
+# Display the first child and hide less relevant data in other panels.
+class TabbedGroup
+       super DocSection
+end
+
+# A group of sections that can be displayed together in a tab panel.
+class PanelGroup
+       super DocSection
+
+       # The title of this group.
+       var group_title: String
+end
+
 # A DocComposite element about a MEntity.
 class MEntityComposite
        super DocComposite
@@ -316,6 +331,7 @@ end
 
 # An article that displaus a list of definition belonging to a MEntity.
 class DefinitionListArticle
+       super TabbedGroup
        super MEntityArticle
 end
 
index 221162b..630d28e 100644 (file)
@@ -36,6 +36,120 @@ class DocHTMLLabel
        end
 end
 
+# A component that display tabbed data.
+class DocTabs
+       super BSComponent
+
+       # HTML id of this component.
+       var html_id: String
+
+       # Text displayed on the tabs dropdown button.
+       var drop_text: String
+
+       # Panels to display in this tab group.
+       var panels = new Array[DocTabPanel]
+
+       # Droplist containing links to panels.
+       #
+       # Can also be used to add external links.
+       var drop_list: DocTabsDrop is lazy do return new DocTabsDrop(html_id, drop_text)
+
+       # Adds a new `panel` to that tab.
+       #
+       # You should always use this instead of `panels.add` because it also set the
+       # `drop_list` entry.
+       fun add_panel(panel: DocTabPanel) do
+               drop_list.add_li panel.render_tab
+               panels.add panel
+       end
+
+       redef fun rendering do
+               if panels.is_empty then return
+               panels.first.is_active = true
+               add "<div role=\"tabpanel\">"
+               if drop_list.items.length > 1 then add drop_list
+               add " <div class=\"tab-content\">"
+               for panel in panels do
+                       add panel
+               end
+               add " </div>"
+               add "</div>"
+       end
+end
+
+# A list of tab regrouped in a dropdown
+class DocTabsDrop
+       super UnorderedList
+
+       # HTML id used by the tabs group.
+       var html_id: String
+
+       # Title to display in the tab item.
+       var html_title: String
+
+       redef fun rendering do
+               add """<ul id="{{{html_id}}}-tabs" class="nav pull-right" role="tablist">"""
+               add """ <li role="presentation" class="dropdown pull-right">"""
+               add """  <a href="#" id="{{{html_id}}}-drop" class="dropdown-toggle"
+                         data-toggle="dropdown" aria-controls="{{{html_id}}}-contents"
+                         aria-expanded="false">"""
+        add html_title
+               add """ <span class="glyphicon glyphicon-menu-hamburger"></span>"""
+               add """ </a>"""
+               add """ <ul class="dropdown-menu" role="menu"
+                        aria-labelledby="{{{html_id}}}-drop" id="{{{html_id}}}-contents">"""
+               for item in items do add item
+               add "  </ul>"
+        add " </li>"
+        add "</ul>"
+       end
+end
+
+# A panel that goes in a DocTabs.
+class DocTabPanel
+       super BSComponent
+
+       # HTML id of this panel.
+       var html_id: String
+
+       # Title of this panel as displayed in the tab label.
+       var tab_title: String
+
+       # HTML content of this panel.
+       var html_content: Writable is writable
+
+       # Is this panel visible by default?
+       var is_active = false
+
+       redef fun rendering do
+               var active = ""
+               if is_active then active = "active in"
+               add "<div role=\"tabpanel\" class=\"tab-pane fade {active}\""
+               add "  id=\"{html_id}\" aria-labelledby=\"{html_id}-tab\">"
+               add html_content
+               add "</div>"
+       end
+
+       private fun render_tab: DocTabItem do return new DocTabItem(tab_title, html_id)
+end
+
+# A ListItem that goes in a DocTabsDrop.
+private class DocTabItem
+       super ListItem
+
+       # Panel id to trigger when the link is clicked.
+       var target_id: String
+
+       redef fun rendering do
+               add "<li{render_css_classes}>"
+               add " <a role=\"tab\" data-toggle=\"tab\" aria-expanded=\"false\" tabindex=\"-1\""
+               add "   id=\"{target_id}-tab\" href=\"#{target_id}\" aria-controls=\"{target_id}\">"
+               add text
+               add " </a>"
+               add "</li>"
+       end
+end
+
 # A HTML tag attribute
 #  `<tag attr="value">`
 #
index a461ba0..4841f02 100644 (file)
@@ -319,6 +319,15 @@ redef class DocComposite
                end
                lst.add_li new ListItem(content)
        end
+
+       # ID used in HTML tab labels.
+       #
+       # We sanitize it for Boostrap JS panels that do not like ":" and "." in ids.
+       var html_tab_id: String is lazy do
+               var id = html_id.replace(":", "")
+               id = id.replace(".", "")
+               return "{id}-tab"
+       end
 end
 
 redef class DocSection
@@ -348,6 +357,24 @@ redef class DocArticle
        end
 end
 
+redef class TabbedGroup
+       redef fun render_body do
+               var tabs = new DocTabs("{html_id}.tabs", "")
+               for child in children do
+                       if child.is_hidden then continue
+                       tabs.add_panel new DocTabPanel(child.html_tab_id, child.toc_title, child)
+               end
+               addn tabs
+       end
+end
+
+redef class PanelGroup
+       redef var html_id is lazy do return "group:{group_title.to_lower.to_snake_case}"
+       redef var html_title = null
+       redef var toc_title is lazy do return group_title
+       redef var is_toc_hidden = true
+end
+
 redef class HomeArticle
        redef var html_id = "article:home"
        redef var html_title = "Overview"
@@ -445,20 +472,21 @@ redef class IntroArticle
        # Link to source to display if any.
        var html_source_link: nullable Writable is noinit, writable
 
-       redef fun render_title do
+       redef fun render_body do
+               var tabs = new DocTabs("{html_id}.tabs", "")
+               var comment = mentity.html_comment
+               if comment != null then
+                       tabs.add_panel new DocTabPanel("{html_tab_id}-comment", "Comment", comment)
+               end
+               for child in children do
+                       if child.is_hidden then continue
+                       tabs.add_panel new DocTabPanel(child.html_tab_id, child.toc_title, child)
+               end
                var lnk = html_source_link
                if lnk != null then
-                       add "<div class='source-link'>"
-                       add lnk
-                       addn "</div>"
+                       tabs.drop_list.items.add new ListItem(lnk)
                end
-               super
-       end
-
-       redef fun render_body do
-               var comment = mentity.html_comment
-               if comment != null then addn comment
-               super
+               addn tabs
        end
 end
 
@@ -502,17 +530,8 @@ redef class DefinitionArticle
        # Link to source to display if any.
        var html_source_link: nullable Writable is noinit, writable
 
-       redef fun render_title do
-               var lnk = html_source_link
-               if lnk != null then
-                       add "<div class='source-link'>"
-                       add lnk
-                       addn "</div>"
-               end
-               super
-       end
-
        redef fun render_body do
+               var tabs = new DocTabs("{html_id}.tabs", "")
                if not is_no_body then
                        var comment
                        if is_short_comment then
@@ -520,9 +539,19 @@ redef class DefinitionArticle
                        else
                                comment = mentity.html_comment
                        end
-                       if comment != null then addn comment
+                       if comment != null then
+                               tabs.add_panel new DocTabPanel("{html_tab_id}-comment", "Comment", comment)
+                       end
                end
-               super
+               for child in children do
+                       if child.is_hidden then continue
+                       tabs.add_panel new DocTabPanel(child.html_tab_id, child.toc_title, child)
+               end
+               var lnk = html_source_link
+               if lnk != null then
+                       tabs.drop_list.items.add new ListItem(lnk)
+               end
+               addn tabs
        end
 end
 
@@ -530,7 +559,7 @@ redef class HierarchyListArticle
        redef var html_id is lazy do return "article:{list_title}_{mentity.nitdoc_id}.hierarchy"
        redef var html_title is lazy do return list_title
        redef fun is_empty do return mentities.is_empty
-       redef fun is_toc_hidden do return mentities.is_empty
+       redef var is_toc_hidden = true
 
        redef fun render_body do
                var lst = new UnorderedList
@@ -542,8 +571,16 @@ redef class HierarchyListArticle
        end
 end
 
-redef class IntrosRedefsListArticle
+redef class IntrosRedefsSection
        redef var html_id is lazy do return "article:{mentity.nitdoc_id}.intros_redefs"
+       redef var toc_title do return "Intros / Redefs"
+       redef var html_title = null
+       redef var html_subtitle = null
+       redef var is_toc_hidden = true
+end
+
+redef class IntrosRedefsListArticle
+       redef var html_id is lazy do return "article:{list_title}_{mentity.nitdoc_id}.intros_redefs"
        redef var html_title is lazy do return list_title
        redef fun is_hidden do return mentities.is_empty
        redef var is_toc_hidden = true
index 347c4dc..1f83e61 100644 (file)
@@ -46,7 +46,7 @@ class AndroidProject
 
        init
        do
-               var annots = modelbuilder.collect_annotations_on_modules("min_api_version", mainmodule)
+               var annots = modelbuilder.collect_annotations_on_modules("android_api_min", mainmodule)
                if not annots.is_empty then
                        var i = annots.pop.arg_as_int(modelbuilder)
                        if i == null then i = 0
@@ -58,7 +58,7 @@ class AndroidProject
                        end
                end
 
-               annots = modelbuilder.collect_annotations_on_modules("max_api_version", mainmodule)
+               annots = modelbuilder.collect_annotations_on_modules("android_api_max", mainmodule)
                if not annots.is_empty then
                        var i = annots.pop.arg_as_int(modelbuilder)
                        if i == null then i = 0
@@ -70,7 +70,7 @@ class AndroidProject
                        end
                end
 
-               var annot = modelbuilder.lookup_annotation_on_modules("target_api_version", mainmodule)
+               var annot = modelbuilder.lookup_annotation_on_modules("android_api_target", mainmodule)
                if annot != null then target_api = annot.arg_as_int(modelbuilder) or else 0
 
                annots = modelbuilder.collect_annotations_on_modules("android_manifest", mainmodule)
diff --git a/tests/sav/test_peek.res b/tests/sav/test_peek.res
new file mode 100644 (file)
index 0000000..edc1121
--- /dev/null
@@ -0,0 +1,33 @@
+# Thi
+# Thi
+s file is pa
+s file is pa
+rt of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var f = new FileReader.open("test_peek.nit")
+
+print f.peek(5)
+print f.read(5)
+
+print f.peek(12)
+print f.read(12)
+
+print f.read_all
+
+print f.peek(2)
+
+f.close
+
+
diff --git a/tests/test_peek.nit b/tests/test_peek.nit
new file mode 100644 (file)
index 0000000..4c1d433
--- /dev/null
@@ -0,0 +1,27 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var f = new FileReader.open("test_peek.nit")
+
+print f.peek(5)
+print f.read(5)
+
+print f.peek(12)
+print f.read(12)
+
+print f.read_all
+
+print f.peek(2)
+
+f.close