/*
This file is part of Badaap Comic Reader.
Copyright (c) 2012 Jeroen Walter
Badaap Comic Reader is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Badaap Comic Reader 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. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Badaap Comic Reader. If not, see .
*/
Ext.define('Comic.controller.Comic', {
extend: 'Ext.app.Controller',
requires: [
'Comic.view.Main',
'Comic.view.Comic',
'Comic.view.ComicSettings',
'Comic.view.ComicInfo',
'Comic.RemoteApi',
'Comic.store.ComicBook'
],
config: {
refs: {
mainview: 'mainview',
comicview: 'comicview',
backbutton: 'comicview #backbutton',
comictitle: 'comicview titlebar',
toolbar: 'comicview toolbar',
slider: 'comicview #slider',
progressbutton: 'comicview #progressbutton',
nextbutton: 'comicview #nextbutton',
previousbutton: 'comicview #previousbutton',
settingsbutton: 'comicview #settingsbutton',
infobutton: 'comicview #infobutton',
nextPageIcon: 'comicview #nextPageIcon',
prevPageIcon: 'comicview #prevPageIcon',
loadingIndicator: 'comicview #loadingIndicator',
imageviewer: 'comicview #imageviewer',
comicsettingsview: { selector: 'comicsettingsview', xtype: 'comicsettingsview', autoCreate: true },
comicinfoview: { selector: 'comicinfoview', xtype: 'comicinfoview', autoCreate: true }
},
control: {
comicview: {
show: 'onShow', // also triggered when the comic view is popped from the main navigation view.... so use active event instead
hide: 'onHide',
singletap: 'onTap',
activate: 'onActivate'
},
slider: {
change: 'onSliderChange'
},
progressbutton: {
tap: 'onProgressButton'
},
nextbutton: {
tap: 'onNextButton'
},
previousbutton: {
tap: 'onPreviousButton'
},
settingsbutton: {
tap: 'onSettingsButton'
},
infobutton: {
tap: 'onInfoButton'
},
backbutton: {
tap: 'onBackButton'
},
imageviewer: {
imageLoaded: 'onImageLoaded',
imageError: 'onImageError',
zoomByTap: 'onZoomByTap',
initDone: 'onImageViewerInitDone',
singletap: 'onSingleTap'
}
}
},
init : function()
{
// called before application.launch()
var me = this;
me.preload_count = 1; // number of pages to preload before and after the current page.
// if 0, preloading is disabled.
me.cache = []; // cache of preloaded page info
me.waiting_for_page = -1; // page that must be displayed once loaded.
Ext.Viewport.on("orientationchange", function() {
//alert("orientationchange");
var imageviewer = me.getImageviewer();
imageviewer.resize();
});
/*
if (Ext.Viewport.supportsOrientation())
{
alert('supportsOrientation()');
}
else
{
alert('NOT supportsOrientation()');
}
*/
},
UpdateSettings: function()
{
var me = this,
imageviewer = me.getImageviewer();
// 1: Fit width, 2: Full page
if (Comic.settings.page_fit_mode == 2)
{
imageviewer.setAutoFitWidth(true);
imageviewer.setAutoFitHeight(true);
}
else
{
// fit width
imageviewer.setAutoFitWidth(true);
imageviewer.setAutoFitHeight(false);
}
imageviewer.setZoomOnSingleTap(Comic.settings.zoom_on_tap == 1);
imageviewer.setZoomOnDoubleTap(Comic.settings.zoom_on_tap == 2);
imageviewer.resize();
},
onImageViewerInitDone: function()
{
var me = this,
imageviewer = me.getImageviewer();
imageviewer.setResizeOnLoad(true);
imageviewer.setErrorImage('resources/no_image_available.jpg');
// 1: Fit width, 2: Full page
if (Comic.settings.page_fit_mode == 2)
{
imageviewer.setAutoFitWidth(true);
imageviewer.setAutoFitHeight(true);
}
else
{
// fit width
imageviewer.setAutoFitWidth(true);
imageviewer.setAutoFitHeight(false);
}
imageviewer.setZoomOnSingleTap(Comic.settings.zoom_on_tap == 1);
imageviewer.setZoomOnDoubleTap(Comic.settings.zoom_on_tap == 2);
// For some reason, I can't access the figure element via the controller refs and control options....
imageviewer.figEl.addListener({
scope: me,
singletap: me.onSingleTap,
doubletap: me.onDoubleTap,
drag: me.onDrag,
dragend: me.onDragEnd
});
},
onHide: function()
{
},
onShow: function()
{
// useless event, gets triggered when the view is popped from a navigation view.....
},
onActivate: function()
{
var me = this,
titlebar = me.getComictitle(),
imageviewer = me.getImageviewer();
me.cache.length = 0;
me.waiting_for_page = -1;
imageviewer.setLoadingMask(false);
if (Comic.new_comic_id == 0)
{
titlebar.setTitle('No comic selected');
imageviewer.loadImage('resources/no_image_available.jpg');
}
else
{
titlebar.setTitle('Opening comic...');
Comic.viewstate.current_comic_id = Comic.new_comic_id;
// Get new comic from server
Comic.RemoteApi.GetComicInfo(Comic.viewstate.current_comic_id, function(success, record) {
if (success)
{
// process response
me.current_comic = record.getData();
Comic.viewstate.current_comic_opened_from_type = 'folder';
Comic.viewstate.current_comic_opened_from_id = Comic.context.id;
me.current_page_nr = me.current_comic.UserCurrentPage | 0;
// use defer so control initialization can finish first
Ext.defer(function() { me.ShowPage(me.current_page_nr); } , 10);
}
else
{
Ext.Msg.alert('Loading failed');
}
});
}
},
onDrag: function(/*Ext.event.Event*/ event, /*HTMLElement*/ node, /*Object*/ options, /*Object*/ eOpts)
{
var me = this,
imageviewer = me.getImageviewer(),
scroller = imageviewer.getScrollable().getScroller(),
nextPageIcon = me.getNextPageIcon(),
prevPageIcon = me.getPrevPageIcon();
if ((scroller.position.x < scroller.getMinPosition().x - Comic.settings.page_turn_drag_threshold) ||
(scroller.position.y < scroller.getMinPosition().y - Comic.settings.page_turn_drag_threshold))
{
prevPageIcon.show();
}
else
if ((scroller.position.x > scroller.getMaxPosition().x + Comic.settings.page_turn_drag_threshold) ||
(scroller.position.y > scroller.getMaxPosition().y + Comic.settings.page_turn_drag_threshold))
{
nextPageIcon.show();
}
else
{
prevPageIcon.hide();
nextPageIcon.hide();
}
},
onDragEnd: function(/*Ext.event.Event*/ event, /*HTMLElement*/ node, /*Object*/ options, /*Object*/ eOpts)
{
var me = this,
imageviewer = me.getImageviewer(),
scroller = imageviewer.getScrollable().getScroller();
if ((scroller.position.x < scroller.getMinPosition().x - Comic.settings.page_turn_drag_threshold) ||
(scroller.position.y < scroller.getMinPosition().y - Comic.settings.page_turn_drag_threshold))
{
this.onPreviousButton();
}
else
if ((scroller.position.x > scroller.getMaxPosition().x + Comic.settings.page_turn_drag_threshold) ||
(scroller.position.y > scroller.getMaxPosition().y + Comic.settings.page_turn_drag_threshold))
{
this.onNextButton();
}
},
onSliderChange: function(slider)
{
var me = this;
me.current_page_nr = Math.round((me.current_comic.PageCount-1) * slider.getValue() / SLIDER_RANGE);
me.ShowPage(me.current_page_nr);
},
onProgressButton: function()
{
/*
var me = this;
delete me.cache[me.current_page_nr];
me.ShowPage(me.current_page_nr);
*/
},
onNextButton: function()
{
var me = this,
nextPageIcon = me.getNextPageIcon();
if (me.current_page_nr < (me.current_comic.PageCount-1))
{
nextPageIcon.show();
//Ext.defer(function() { this.hide(); }, 500, nextPageIcon);
Ext.defer(function() { me.ShowPage(++me.current_page_nr); }, 150);
//me.ShowPage(++me.current_page_nr);
}
else
{
/*
if (Comic.settings.open_next_comic == 1)
{
// TODO: need a way to determine what is the next comic...
}
else
*/
{
me.onBackButton();
}
}
},
onPreviousButton: function()
{
var me = this,
prevPageIcon = me.getPrevPageIcon();
if (me.current_page_nr > 0)
{
prevPageIcon.show();
Ext.defer(function() { this.hide(); }, 500, prevPageIcon);
Ext.defer(function() { me.ShowPage(--me.current_page_nr); }, 150);
//me.ShowPage(--me.current_page_nr);
}
else
{
me.onBackButton();
}
},
onBackButton: function()
{
Comic.viewstate.current_comic_id = null;
Comic.viewstate.current_comic_opened_from_type = null;
Comic.viewstate.current_comic_opened_from_id = null;
var me = this,
d=new Date(),
n=d.toJSON();
Comic.context.record.beginEdit();
Comic.context.record.set("UserOpenedTimeAsText", n);
Comic.context.record.set("UserCurrentPage", me.current_page_nr);
Comic.context.record.set("UserLastPageRead", me.current_page_nr);
Comic.context.record.endEdit();
Comic.context.record.commit();
this.getMainview().pop(1);
},
onSingleTap: function(/*Ext.event.Event*/ event, /*HTMLElement*/ node, /*Object*/ options, /*Object*/ eOpts)
{
// This handler is called for both the figure and its image element, because of event bubbling.
// If clicked in the image, then the event for the image comes before the event of the figure.
// In order to prevent double page turns, stop event propagation here.
var me = this;
if (event.pageX < Comic.settings.page_change_area_width)
{
me.onPreviousButton();
event.stopPropagation();
return true;
}
else
if (event.pageX > window.outerWidth - Comic.settings.page_change_area_width)
{
me.onNextButton();
event.stopPropagation();
return true;
}
else
{
if (Comic.settings.toggle_paging_bar == 1)
{
me.onToggleToolbars();
}
event.stopPropagation();
return false;
}
},
onDoubleTap: function(/*Ext.event.Event*/ event, /*HTMLElement*/ node, /*Object*/ options, /*Object*/ eOpts)
{
// This handler is called for both the figure and its image element, because of event bubbling.
// If clicked in the image, then the event for the image comes before the event of the figure.
// In order to prevent double page turns, stop event propagation here.
var me = this;
if (Comic.settings.toggle_paging_bar == 2)
{
me.onToggleToolbars();
}
event.stopPropagation();
return false;
},
onToggleToolbars: function(ev, t)
{
var titlebar = this.getComictitle(),
toolbar = this.getToolbar();
if (titlebar.isHidden())
{
titlebar.show();
toolbar.show();
}
else
{
titlebar.hide();
toolbar.hide();
}
// no further processing
return false;
},
onZoomByTap: function(ev, t)
{
return true;
},
onImageError: function()
{
var me = this;
console.log('Error while loading the image.');
},
onImageLoaded: function()
{
var me = this,
imageviewer = me.getImageviewer(),
scroller = imageviewer.getScrollable().getScroller(),
nextPageIcon = me.getNextPageIcon(),
previousPageIcon = me.getPrevPageIcon();
console.log('comic onImageLoaded');
//scroller.stopAnimation();
me.getLoadingIndicator().hide();
nextPageIcon.hide();
previousPageIcon.hide();
scroller.scrollTo(0,0);
me.getSlider().setValue((me.current_page_nr / (me.current_comic.PageCount-1)) * SLIDER_RANGE);
if (me.preload_count > 0)
{
Ext.defer(function() {
//me.PreloadPages();
me.PreloadPage(me.current_page_nr+1);
}, 10 );
}
if (me.current_comic)
{
}
},
onInfoButton: function()
{
var me = this,
view = me.getComicinfoview();
view.comic = me.current_comic;
me.getMainview().push(view);
},
onSettingsButton: function()
{
var me = this;
if (!me.overlay)
{
me.overlay = Ext.Viewport.add(me.getComicsettingsview());
}
me.overlay.show();
},
ShowPage: function(pagenr)
{
var me = this,
imageviewer = me.getImageviewer(),
scroller = imageviewer.getScrollable().getScroller(),
titlebar = me.getComictitle(),
progressbutton = me.getProgressbutton();
if (pagenr < 0 || pagenr >= me.current_comic.PageCount)
{
console.log("pagenr " + pagenr + " out of bounds [0.."+(me.current_comic.PageCount-1)+"]");
return;
}
/*
var cachedpages = "";
function addcache(element, index, array) {
{
if (element.img)
cachedpages = cachedpages + " " + index;
}
}
me.cache.forEach(addcache);
titlebar.setTitle(me.current_comic.Caption + " " + (pagenr + 1)+ "/" + me.current_comic.PageCount + cachedpages);
*/
titlebar.setTitle(me.current_comic.Caption + " " + (pagenr + 1)+ "/" + me.current_comic.PageCount);
// todo: show loading indicator in toolbar and remove it when image is loaded.
progressbutton.setText("" + (pagenr + 1)+ "/" + me.current_comic.PageCount);
var now = (new Date()).toJSON();
Comic.RemoteApi.UpdateProgress(Comic.viewstate.current_comic_id, me.current_page_nr,
function() {
scroller.scrollTo(0,0);
me.getSlider().setValue((pagenr / (me.current_comic.PageCount-1)) * SLIDER_RANGE);
if ((me.preload_count > 0) && me.cache[pagenr] && me.cache[pagenr].img)
{
console.log("showpage from cache");
imageviewer.loadImage(me.cache[pagenr].src);
/*
imageviewer.setImage(me.cache[pagenr].img);
me.cache[pagenr].img = null;
delete me.cache[pagenr].img;
*/
}
else
{
console.log("showpage loadimage");
me.waiting_for_page = pagenr;
me.getLoadingIndicator().show();
imageviewer.loadImage(Comic.RemoteApi.GetImageUrl(me.current_comic.Id, pagenr));
}
});
},
PreloadPage: function(pagenr)
{
var me = this;
if (pagenr < 0 || pagenr >= me.current_comic.PageCount)
{
return;
}
if (me.cache[pagenr])
{
if (!me.cache[pagenr].img)
{
me.PreloadImage(pagenr);
}
return;
}
me.cache[pagenr] = {};
me.cache[pagenr].src = Comic.RemoteApi.GetImageUrl(me.current_comic.Id, pagenr);
me.PreloadImage(pagenr);
},
PreloadImage: function(pagenr)
{
var me = this;
if (pagenr < 0 || pagenr >= me.current_comic.PageCount)
{
return;
}
if (!me.cache[pagenr])
{
console.log("PreloadImage called with no cache entry for page " + pagenr);
return;
}
console.log("cache preload");
me.cache[pagenr].img = Ext.dom.Element.get(new Image());
me.cache[pagenr].img.dom.src = me.cache[pagenr].src;
me.cache[pagenr].img.dom.onload = function()
{
console.log("cache onload");
};
me.cache[pagenr].img.dom.onerror = function()
{
//Ext.Msg.alert('Error while loading image ' + image.getSrc());
console.log('Error while loading image ' );
//me.cache[pagenr].img.destroy();
//delete me.cache[pagenr].img;
};
//me.cache[pagenr].img = Ext.create('Ext.Img', {
// src: me.cache[pagenr].src,
// mode: 'element', // create
instead of
// listeners: {
// load: function( /*Ext.Img*/ image, /*Ext.EventObject*/ e, /*Object*/ eOpts )
// {
// console.log("cache onload");
// },
// error: function( /*Ext.Img*/ image, /*Ext.EventObject*/ e, /*Object*/ eOpts )
// {
// Ext.Msg.alert('Error while loading image ' + image.getSrc());
// console.log('Error while loading image ' + image.getSrc());
// me.cache[pagenr].img.destroy();
// delete me.cache[pagenr].img;
// },
// }
//});
},
PreloadPages: function()
{
var me = this,
i = 0;
// Clear old cache images, not the page info.
for (i = 0; i <= me.current_page_nr - me.preload_count - 1; i++)
{
if (me.cache[i] && me.cache[i].img)
{
me.cache[i].img.destroy();
delete me.cache[i].img;
}
}
for (i = me.current_page_nr + me.preload_count + 1; i < me.current_comic.PageCount; i++)
{
if (me.cache[i] && me.cache[i].img)
{
me.cache[i].img.destroy();
delete me.cache[i].img;
}
}
// Preload the next and previous pages.
for (i = me.current_page_nr+1; i <= me.current_page_nr + me.preload_count; i++)
{
me.PreloadPage(i);
}
for (i = me.current_page_nr - 1; i >= me.current_page_nr - me.preload_count; i--)
{
me.PreloadPage(i);
}
}
});