tgios 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YjFlOTkxYjQ2MGRmMDAwNDE5MTZhYzBhZWI3MzQ5Y2U4NTcwOTcyYQ==
5
+ data.tar.gz: !binary |-
6
+ NGNkYThiNTU4YWUxMjc2OTQxOTkxYWFkMjFiMWIzYjkyNDQxZThhNQ==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MzBkZDQzYzllMjNiNGI1MzNkNTk3ZWM5ZWUyNzU4NDk1YTM4NDFlNWFiNWZh
10
+ ZmJhZGI4MGFiZDc1YWExZDcxNmQwNmRhYWQxYjE0ZjJiZjMwNzNkMzBjOGEw
11
+ MDU5MzUyZWMyZTQ5MDYxNjIxZmU1ZWIyNjg1Nzc5NmNiMGQyMzQ=
12
+ data.tar.gz: !binary |-
13
+ NDlkNDkwMGZmY2U5YWNjYmNkNzU1ZDY5ZGJiNjk3MDgxMTQyYWVmYTNlZTEw
14
+ OTliODJhMjk5NGYwNjk0YzBjMTMyODdlODZjOGM3MTAxYmU2YjBkNDc1NzNh
15
+ MjRjMzJjYTYzOWU3MGY0MzFlNDczNTEzMDljMWY0OGU1NWRlYzI=
data/.gitignore ADDED
@@ -0,0 +1,23 @@
1
+ *.gem
2
+
3
+ .repl_history
4
+ build
5
+ tags
6
+ app/pixate_code.rb
7
+ resources/*.nib
8
+ resources/*.momd
9
+ resources/*.storyboardc
10
+ .DS_Store
11
+ nbproject
12
+ .redcar
13
+ #*#
14
+ *~
15
+ *.sw[po]
16
+ .eprj
17
+ .sass-cache
18
+ .idea
19
+ .build
20
+ build-*
21
+ .dat*
22
+ .ruby-gemset
23
+ .ruby-version
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :test, :development do
4
+ gem 'rake'
5
+ gem 'motion-stump'
6
+ end
7
+
8
+ gemspec
9
+
10
+ #gem 'plastic_cup', '>=0.1.1'
11
+ #gem 'sugarcube', '1.1.0', require: 'sugarcube-classic'
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ tgios (0.0.1)
5
+ awesome_print_motion
6
+ motion-layout
7
+ plastic_cup (>= 0.1.1)
8
+ sugarcube (= 1.1.0)
9
+
10
+ GEM
11
+ remote: https://rubygems.org/
12
+ specs:
13
+ awesome_print_motion (0.1.0)
14
+ motion-layout (0.0.1)
15
+ motion-stump (0.3.0)
16
+ plastic_cup (0.1.1)
17
+ rake (10.1.0)
18
+ sugarcube (1.1.0)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ motion-stump
25
+ rake
26
+ tgios!
data/LICENSE ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2014, April
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ Redistributions in binary form must reproduce the above copyright notice, this
11
+ list of conditions and the following disclaimer in the documentation and/or
12
+ other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
18
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
21
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
23
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+ $:.unshift("/Library/RubyMotion/lib")
3
+ require 'motion/project/template/ios'
4
+
5
+ begin
6
+ require 'bundler'
7
+ Bundler.require
8
+ require 'motion-stump'
9
+ require 'sugarcube'
10
+ require 'plastic_cup'
11
+ require 'plastic_cup/stylesheet'
12
+ rescue LoadError
13
+ end
14
+
15
+ Motion::Project::App.setup do |app|
16
+ # Use `rake config' to see complete project settings.
17
+ app.name = 'tgios'
18
+ app.identifier = 'com.tofugear.tgios'
19
+ app.specs_dir = "spec/"
20
+ end
@@ -0,0 +1,14 @@
1
+ class AppDelegate
2
+ def application(application, didFinishLaunchingWithOptions:launchOptions)
3
+ return true if RUBYMOTION_ENV == 'test'
4
+
5
+ @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
6
+ ctlr = MyController.new
7
+ @window.rootViewController = ctlr
8
+ @window.makeKeyAndVisible
9
+ true
10
+ end
11
+
12
+ class MyController < UIViewController
13
+ end
14
+ end
@@ -0,0 +1,50 @@
1
+ module Tgios
2
+ class AnimatableView < UIView
3
+ DURATION = 0.25
4
+
5
+ def initWithFrame(frame)
6
+ super
7
+ bg_view = PlasticCup::Base.style(UIView.new,
8
+ frame: self.bounds,
9
+ backgroundColor: :white.uicolor,
10
+ alpha: 0.95)
11
+ self.addSubview(bg_view)
12
+ self
13
+ end
14
+
15
+ def show_animated
16
+ @show_notification ||= NSNotification.notificationWithName(
17
+ UIKeyboardWillShowNotification,
18
+ object: self,
19
+ userInfo:{UIKeyboardFrameEndUserInfoKey=> NSValue.valueWithCGRect(self.frame),
20
+ UIKeyboardAnimationCurveUserInfoKey=> UIViewAnimationOptionCurveEaseInOut,
21
+ UIKeyboardAnimationDurationUserInfoKey=> DURATION})
22
+ UIView.animateWithDuration(DURATION, animations: ->{
23
+ NSNotificationCenter.defaultCenter.postNotification(@show_notification)
24
+ self.alpha = 1.0
25
+ frame = self.frame
26
+ frame.origin.y = self.superview.frame.size.height - self.bounds.size.height
27
+ self.frame = frame
28
+ })
29
+ @is_shown = true
30
+ end
31
+
32
+ def hide_animated
33
+ if @is_shown
34
+ @hide_notification ||= NSNotification.notificationWithName(
35
+ UIKeyboardWillHideNotification,
36
+ object: self,
37
+ userInfo:{UIKeyboardAnimationCurveUserInfoKey=> UIViewAnimationOptionCurveEaseInOut,
38
+ UIKeyboardAnimationDurationUserInfoKey=> DURATION})
39
+ UIView.animateWithDuration(DURATION, animations: ->{
40
+ NSNotificationCenter.defaultCenter.postNotification(@hide_notification)
41
+ self.alpha = 0.0
42
+ frame = self.frame
43
+ frame.origin.y = self.superview.frame.size.height
44
+ self.frame = frame
45
+ })
46
+ @is_shown = false
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,38 @@
1
+ module Tgios
2
+ class BindingBase
3
+ def initialize(*arg)
4
+ @hook_bindings = []
5
+ end
6
+
7
+ def prepareForRelease
8
+ @hook_bindings = nil
9
+ onPrepareForRelease
10
+ end
11
+
12
+ def onPrepareForRelease
13
+ raise NotImplementedError.new("prepareForRelease not overridden for class #{self.class.name}")
14
+ end
15
+
16
+ def hook(control, event, &block)
17
+ binding=if control.is_a?(UIButton)
18
+ UIButtonBinding.new.bind(control).on(event, &block)
19
+ end
20
+
21
+ @hook_bindings << binding
22
+ binding
23
+
24
+ end
25
+
26
+ def unhook(control, event)
27
+ if control.is_a?(UIButton)
28
+ UIButtonBinding.unbind(control)
29
+ end
30
+ end
31
+
32
+ def dealloc
33
+ ap "#{self.class.name} dealloc"
34
+ super
35
+ end
36
+ end
37
+
38
+ end
@@ -0,0 +1,30 @@
1
+
2
+ include SugarCube::CoreGraphics
3
+ module Tgios
4
+ class CommonUIUtility
5
+ def self.imageFromColor(color)
6
+
7
+ rect=Rect(0,0,1,1)
8
+ UIGraphicsBeginImageContext(rect.size)
9
+ context=UIGraphicsGetCurrentContext()
10
+ uicolor = color.is_a?(UIColor) ? color : color.uicolor
11
+ CGContextSetFillColorWithColor(context, uicolor.CGColor)
12
+ CGContextFillRect(context, rect)
13
+ image=UIGraphicsGetImageFromCurrentImageContext()
14
+ UIGraphicsEndImageContext()
15
+ image
16
+ end
17
+
18
+ def self.fix_orientation(image)
19
+ if image.imageOrientation == UIImageOrientationUp
20
+ image
21
+ else
22
+ UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
23
+ image.drawInRect([[0,0], image.size])
24
+ normalized_image = UIImage.UIGraphicsGetImageFromCurrentImageContext
25
+ UIGraphicsEndImageContext()
26
+ normalized_image
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,35 @@
1
+ module Tgios
2
+ module CustomMethod
3
+ def self.included(base)
4
+ base.class_eval do
5
+ extend ClassMethods
6
+ end
7
+
8
+ end
9
+
10
+ def on(event_name, &block)
11
+ @events[event_name]=block
12
+ end
13
+
14
+ def off(*event_names)
15
+ event_names.each {|event_name| @events.delete(event_name) }
16
+ end
17
+
18
+ module ClassMethods
19
+ def define_custom_method(name=[])
20
+ name.each do |fld|
21
+ define_method fld do
22
+ self.instance_variable_get(:"@#{fld}")
23
+ end
24
+ define_method "#{fld}=" do |value|
25
+ old_value=self.instance_variable_get(:"@#{fld}")
26
+ self.instance_variable_set(:"@#{fld}", value)
27
+ @events[:value_changed].call(self, fld, old_value, value) unless @events.nil? || @events[:value_changed].nil?
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,37 @@
1
+ module Tgios
2
+ module ExtendedUITableView
3
+ include PlasticCup
4
+
5
+ def add_full_table_view_to(view)
6
+ table = Base.style(UITableView.grouped, :grouped_table)
7
+ Motion::Layout.new do |l|
8
+ l.view view
9
+ l.subviews 'table' => table
10
+ l.vertical '|[table]|'
11
+ l.horizontal '|[table]|'
12
+ end
13
+ table
14
+ end
15
+
16
+ def add_title_to_table_header(title, table)
17
+ frame = table.bounds
18
+ frame.size.height = 45
19
+ table_header = UIView.alloc.initWithFrame(frame)
20
+ table.tableHeaderView = table_header
21
+ add_title_to_view(title, table_header)
22
+
23
+ end
24
+
25
+ def add_title_to_view(title, view)
26
+
27
+ Motion::Layout.new do |l|
28
+ l.view view
29
+ l.subviews 'label' => Base.style(UILabel.new, text: title,
30
+ font: UIFont.boldSystemFontOfSize(19),
31
+ adjustsFontSizeToFitWidth: true)
32
+ l.vertical '|-10-[label]|'
33
+ l.horizontal '|-10-[label]-10-|'
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,42 @@
1
+ module Tgios
2
+ class ExtendedUIViewController < UIViewController
3
+ def viewDidLoad
4
+ super
5
+ self.edgesForExtendedLayout = UIRectEdgeNone if self.respond_to?(:edgesForExtendedLayout)
6
+ @bindings=[]
7
+ end
8
+
9
+ def prepareForRelease
10
+ @bindings=nil
11
+ onPrepareForRelease
12
+ end
13
+
14
+ def onPrepareForRelease
15
+ raise NotImplementedError.new("onPrepareForRelease not overridden for class #{self.class.name}")
16
+ end
17
+
18
+ def hook(control, event, &block)
19
+ binding=if control.is_a?(UIButton)
20
+ UIButtonBinding.new.bind(control).on(event, &block)
21
+ end
22
+
23
+ @bindings << binding
24
+ binding
25
+
26
+ end
27
+
28
+ def viewDidDisappear(animated)
29
+ if self.isMovingFromParentViewController
30
+ ap "#{self.class.name} view moving away, prepare for release"
31
+ # cut off all crap to avoid memory leak
32
+ self.prepareForRelease()
33
+ end
34
+ super
35
+ end
36
+
37
+ def dealloc
38
+ ap "#{self.class.name} dealloc"
39
+ super
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,60 @@
1
+ module Tgios
2
+ class ImageLoader < BindingBase
3
+
4
+ def initialize(url)
5
+ super
6
+ @url = url
7
+ @events = {}
8
+ end
9
+
10
+ def on(event, &block)
11
+ @events[event]=block
12
+ end
13
+
14
+ def load
15
+ image = UIImage.imageWithContentsOfFile(self.file_path)
16
+ if image.nil?
17
+ AFMotion::HTTP.get(@url) do |result|
18
+ image = UIImage.imageWithData(result.object)
19
+ @events[:image_loaded].call(image, result.success?) unless @events.nil? || @events[:image_loaded].nil?
20
+ NSFileManager.defaultManager.createFileAtPath(self.file_path, contents: result.object, attributes:nil)
21
+ end
22
+ else
23
+ @events[:image_loaded].call(image, true) unless @events.nil? || @events[:image_loaded].nil?
24
+ end
25
+ end
26
+
27
+ def self.base_path
28
+ @base_path ||= "#{NSTemporaryDirectory()}web/"
29
+ end
30
+
31
+ def filename
32
+ @filename ||= (
33
+ nsurl = NSURL.URLWithString(@url)
34
+ path = "#{nsurl.host}#{nsurl.path}"
35
+ CGI.escape(path)
36
+ )
37
+ end
38
+
39
+ def file_path
40
+ @file_path ||= (
41
+ NSFileManager.defaultManager.createDirectoryAtPath(self.class.base_path,
42
+ withIntermediateDirectories: true,
43
+ attributes: nil,
44
+ error: nil)
45
+ "#{self.class.base_path}#{self.filename}"
46
+ )
47
+ end
48
+
49
+ def self.clear_files
50
+ fm = NSFileManager.defaultManager
51
+ fm.contentsOfDirectoryAtPath(self.base_path, error:nil).each do |filename|
52
+ fm.removeItemAtPath("#{self.base_path}#{filename}", error: nil)
53
+ end
54
+ end
55
+
56
+ def onPrepareForRelease
57
+ @events = nil
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,47 @@
1
+ include PlasticCup
2
+ module Tgios
3
+ module LoadingIndicator
4
+ def add_loading_indicator_to(view)
5
+ Base.add_style_sheet(:loading_view, {
6
+ backgroundColor: :black.uicolor,
7
+ alpha: 0.5
8
+ })
9
+ @loading_view = Base.style(UIView.new, hidden: true)
10
+ base_view = Base.style(UIView.new, :loading_view)
11
+ @indicator = UIActivityIndicatorView.large
12
+ [{super_view: view, subview: @loading_view}, {super_view: @loading_view, subview: base_view}, {super_view: @loading_view, subview: @indicator}].each do |hash|
13
+ Motion::Layout.new do |l|
14
+ l.view hash[:super_view]
15
+ l.subviews 'subview' => hash[:subview]
16
+ l.vertical '|[subview]|'
17
+ l.horizontal '|[subview]|'
18
+ end
19
+ end
20
+ @label = Base.style(UILabel.new,
21
+ frame: view.bounds,
22
+ font: lambda {UIFont.systemFontOfSize(22)},
23
+ textAlignment: :center.uialignment,
24
+ backgroundColor: :clear.uicolor,
25
+ textColor: :white.uicolor)
26
+ @label.sizeToFit
27
+ Motion::Layout.new do |l|
28
+ l.view @loading_view
29
+ l.subviews 'label' => @label
30
+ l.vertical '[label]-290-|'
31
+ l.horizontal '|-20-[label]-20-|'
32
+ end
33
+ end
34
+
35
+ def start_loading(text='')
36
+ @label.text = text
37
+ self.view.endEditing(true)
38
+ @loading_view.hidden = false
39
+ @indicator.startAnimating
40
+ end
41
+
42
+ def stop_loading
43
+ @loading_view.hidden = true
44
+ @indicator.stopAnimating
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,20 @@
1
+ module Tgios
2
+ module ModelErrorsHelper
3
+ def has_error_in_fields_and_errors_for_name(fields, errors, field_name)
4
+ if errors.is_a?(Hash)
5
+ errors.has_key?(field_name) || errors.has_key?(related_name_in_fields(fields, field_name))
6
+ else
7
+ false
8
+ end
9
+ end
10
+
11
+ def related_name_in_fields(fields, field_name)
12
+ field = fields.find{|fld| fld[:name] == field_name}
13
+ if field.is_a?(Hash)
14
+ field[:related_name]
15
+ else
16
+ nil
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ module Tgios
2
+ class NSDateHelper
3
+ def self.to_nsdate(date_string)
4
+ @formatter ||= (
5
+ @formatter = NSDateFormatter.new
6
+ @formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
7
+ @formatter.timeZone = NSTimeZone.timeZoneForSecondsFromGMT(0)
8
+ @formatter
9
+ )
10
+ date = @formatter.dateFromString(date_string)
11
+ if date.nil?
12
+ @formatter2 ||= (
13
+ @formatter2 = NSDateFormatter.new
14
+ @formatter2.dateFormat = "yyyy-MM-dd HH:mm:ss"
15
+ @formatter2.timeZone = NSTimeZone.timeZoneForSecondsFromGMT(0)
16
+ @formatter2
17
+ )
18
+ date = @formatter2.dateFromString(date_string).utc
19
+
20
+ else
21
+ date.utc
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ module Tgios
2
+ class PhotoController < ExtendedUIViewController
3
+ include LoadingIndicator
4
+ attr_accessor :url
5
+
6
+ def viewDidLoad
7
+ super
8
+ self.view.backgroundColor = :black.uicolor
9
+
10
+ add_loading_indicator_to(self.view)
11
+ unless @url.nil?
12
+ start_loading
13
+ image_loader = ImageLoader.new(@url)
14
+ image_loader.on(:image_loaded) do |image, success|
15
+ stop_loading
16
+ if success
17
+ ap 'image loaded'
18
+ # TODO: use motion layout or other way to handle frame size (or allow full screen)
19
+ small_frame = self.view.bounds
20
+ small_frame.size.height -= 20 + 44 if small_frame == UIScreen.mainScreen.bounds
21
+
22
+ scroll_view = PhotoScrollView.alloc.initWithFrame(small_frame, image: image)
23
+ self.view.addSubview(scroll_view)
24
+ end
25
+ image_loader.prepareForRelease
26
+ end
27
+ image_loader.load
28
+
29
+ end
30
+ end
31
+
32
+ def onPrepareForRelease
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,61 @@
1
+ module Tgios
2
+ class PhotoScrollView < UIScrollView
3
+ MAX_SCALE = 4.0
4
+
5
+ def initWithFrame(frame, image: image)
6
+ initWithFrame(frame)
7
+ ap "init #{self.class.name}"
8
+ self.showsVerticalScrollIndicator = false
9
+ self.showsHorizontalScrollIndicator = false
10
+ self.bouncesZoom = true
11
+ self.decelerationRate = UIScrollViewDecelerationRateFast
12
+ self.delegate = self
13
+ self.backgroundColor = :clear.uicolor
14
+
15
+ page_rect = CGRectMake(0, 0, image.size.width, image.size.height)
16
+
17
+ img_scale = frame.size.width / page_rect.size.width
18
+ fit_scale = frame.size.height / page_rect.size.height
19
+ fit_scale = img_scale if img_scale < fit_scale
20
+
21
+ page_rect.size = CGSizeMake(page_rect.size.width * img_scale, page_rect.size.height * img_scale)
22
+
23
+ @image_view = PlasticCup::Base.style(UIImageView.new,
24
+ image: image,
25
+ frame: page_rect,
26
+ contentMode: UIViewContentModeScaleAspectFit)
27
+ self.addSubview(@image_view)
28
+
29
+ self.zoomScale = 0.995 if page_rect.size.height > frame.size.height
30
+
31
+ self.maximumZoomScale = MAX_SCALE / img_scale
32
+ self.minimumZoomScale = fit_scale / img_scale
33
+
34
+ self
35
+ end
36
+
37
+ def layoutSubviews
38
+ super
39
+
40
+ bsize = self.bounds.size
41
+ center_frame = @image_view.frame
42
+
43
+ center_frame.origin.x = center_frame.size.width < bsize.width ? (bsize.width - center_frame.size.width) / 2.0 : 0
44
+ center_frame.origin.y = center_frame.size.height < bsize.height ? (bsize.height - center_frame.size.height) / 2.0 : 0
45
+
46
+ @image_view.frame = center_frame
47
+ @image_view.contentScaleFactor = 1.0
48
+
49
+ end
50
+
51
+ def viewForZoomingInScrollView(scrollView)
52
+ @image_view
53
+ end
54
+
55
+ def dealloc
56
+ ap "dealloc #{self.class.name}"
57
+ super
58
+ end
59
+
60
+ end
61
+ end