mirror of
https://github.com/flynx/ImageGrid.git
synced 2025-10-30 02:40:08 +00:00
added gen 3 ui code (still a work in progress...)
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
parent
226140de06
commit
00151937ff
61
ui/Gen3-TODO.otl
Executable file
61
ui/Gen3-TODO.otl
Executable file
@ -0,0 +1,61 @@
|
||||
[_] 0% Generation 3 current todo
|
||||
[_] manual sort -- shift left/right
|
||||
[_] migrate the infinite ribbon code
|
||||
[_] migrate the PortableMag generic code
|
||||
[_] write basic align code
|
||||
|
||||
|
||||
Generation 3 UI implementation
|
||||
Infinite ribbon (lib)
|
||||
cyclic ribbon
|
||||
image block generation
|
||||
image block update
|
||||
ribbon head/tail management
|
||||
| must be adaptive to current user scroll speed...
|
||||
|
|
||||
| at least a couple of screens at current zoom level...
|
||||
Partial save/load
|
||||
| save only a block or changed data...
|
||||
Adaptive preview size (lib)
|
||||
Multible ribbon (reuse)
|
||||
User actions
|
||||
| see [[controls.otl]] for basic actions...
|
||||
|
|
||||
| additional actions:
|
||||
toggle mark image
|
||||
| should include a set of marking operations
|
||||
mark between
|
||||
| mark all images between closest marks
|
||||
unmark set
|
||||
mark to/from
|
||||
show marked only in ribbon (crop selection)
|
||||
crop image
|
||||
| shows a red/blue rectangle around image
|
||||
|
|
||||
| can be:
|
||||
| turned +/- 90 deg
|
||||
| turned arbitrarily
|
||||
| scaled with constrained proportions
|
||||
show crop as red rectangle
|
||||
show only cropped area
|
||||
show crop as black veil
|
||||
add note to image
|
||||
| a-la flickr notes...
|
||||
edit IPCT
|
||||
rotate image
|
||||
| +/- 90 deg
|
||||
UI modes
|
||||
single ribbon
|
||||
show images above/below in current ribbon
|
||||
show marked only
|
||||
multiple ribbons
|
||||
show images above/below
|
||||
show marked only
|
||||
single image
|
||||
|
||||
TODO
|
||||
action visual indication
|
||||
|
||||
|
||||
.
|
||||
| vim:set spell :
|
||||
153
ui/ImageGrid.js
Executable file
153
ui/ImageGrid.js
Executable file
@ -0,0 +1,153 @@
|
||||
/**********************************************************************
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* This should work over three contexts:
|
||||
* - archive (full)
|
||||
* full data available remotely
|
||||
* handle global operations
|
||||
* - local data (full or partial)
|
||||
* full or partial set of data available locally
|
||||
* handle global operations (if full data-set is available)
|
||||
* handle local operations (if enough data is available)
|
||||
* - local view (partial)
|
||||
* only the rendered UI and cache
|
||||
*
|
||||
*
|
||||
**********************************************************************/
|
||||
|
||||
var Context = {
|
||||
// the selection query used to get data...
|
||||
// NOTE: this should support operations to get next and prev batches if it's partial
|
||||
// XXX we do not care about this yet
|
||||
query: null,
|
||||
|
||||
// this can be:
|
||||
// 'full' - indicating that all the data is available locally
|
||||
// 'partial' - indicating that only part of the data is available
|
||||
data_state: 'full',
|
||||
|
||||
data: {
|
||||
// current image...
|
||||
current: null,
|
||||
|
||||
// images, hashed by GUID...
|
||||
images: {
|
||||
},
|
||||
|
||||
// list of ribbons...
|
||||
ribbons: [
|
||||
// list of GUIDs in sort order...
|
||||
[]
|
||||
],
|
||||
// list of marked GUIDs...
|
||||
marked: [
|
||||
],
|
||||
}
|
||||
|
||||
view: null,
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Helpers...
|
||||
*/
|
||||
|
||||
// retrun viewer width in images...
|
||||
function getViewImages(){
|
||||
// XXX
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* User actions...
|
||||
*/
|
||||
|
||||
/* Focus an image...
|
||||
*
|
||||
* n can be:
|
||||
* - position relative to current
|
||||
* -1 is previous image, +1 next
|
||||
* - GUID
|
||||
* if GUID is present in context select it.
|
||||
*/
|
||||
function focusImage(n){
|
||||
// XXX
|
||||
}
|
||||
|
||||
// shorthands...
|
||||
function nextImage(){
|
||||
return focusImage(1)
|
||||
}
|
||||
function prevImage(){
|
||||
return focusImage(-1)
|
||||
}
|
||||
// NOTE: here n is the multiplier to the screen width of images...
|
||||
function nextViewImages(n){
|
||||
n = n == null ? 1 : n
|
||||
return focusImage(getViewImages()*n)
|
||||
}
|
||||
function prevViewImages(n){
|
||||
n = n == null ? -1 : -n
|
||||
return focusImage(getViewImages()*n)
|
||||
}
|
||||
|
||||
function firstImage(){
|
||||
// XXX
|
||||
}
|
||||
function lastImage(){
|
||||
// XXX
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Focus a ribbon...
|
||||
*
|
||||
* n can be:
|
||||
* - position relative to current
|
||||
* -1 is previous image, +1 next
|
||||
* - GUID (???)
|
||||
* if GUID is present in context select it.
|
||||
*
|
||||
* NOTE: this will also focus the closest image...
|
||||
*/
|
||||
function focusRibbon(n){
|
||||
// XXX
|
||||
}
|
||||
|
||||
// shorthands...
|
||||
function ribbonAbove(n){
|
||||
n = n == null ? -1 : n
|
||||
return focusRibbon(n)
|
||||
}
|
||||
function ribbonBelow(n){
|
||||
n = n == null ? 1 : -n
|
||||
return focusRibbon(n)
|
||||
}
|
||||
|
||||
function topRibbon(){
|
||||
// XXX
|
||||
}
|
||||
function bottomRibbon(){
|
||||
// XXX
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Marking...
|
||||
*
|
||||
* NOTE: n can be null, then current image is marked.
|
||||
*/
|
||||
function toggleMark(n){
|
||||
// XXX
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* vim:set sw=4 ts=4 : */
|
||||
269
ui/index.html
Executable file
269
ui/index.html
Executable file
@ -0,0 +1,269 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>ImageGrid.Viewer</title>
|
||||
|
||||
|
||||
<style>
|
||||
|
||||
.viewer {
|
||||
position: relative;
|
||||
width: 800px;
|
||||
height: 600px;
|
||||
/*overflow: hidden;*/
|
||||
overflow: auto;
|
||||
|
||||
border: solid blue 1px;
|
||||
}
|
||||
|
||||
|
||||
.ribbon-set {
|
||||
}
|
||||
.ribbon-set:empty:after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
content: "Empty";
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.ribbon {
|
||||
position: relative;
|
||||
display: block;
|
||||
height: auto;
|
||||
min-width: 0px;
|
||||
overflow: visible;
|
||||
white-space: nowrap;
|
||||
font-size: 0;
|
||||
|
||||
/*
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
*/
|
||||
}
|
||||
.ribbon:first-child {
|
||||
margin-top: 0px;
|
||||
}
|
||||
.ribbon:last-child {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
/* XXX do we actually need this? */
|
||||
.current.ribbon {
|
||||
}
|
||||
|
||||
|
||||
.image {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-align;left;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
font-size: 12pt;
|
||||
|
||||
background: black;
|
||||
box-sizing:border-box;
|
||||
border: solid gray 1px;
|
||||
color: white;
|
||||
}
|
||||
.current.image {
|
||||
background: red;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
<script src="jquery.js"></script>
|
||||
|
||||
<script>
|
||||
|
||||
/*
|
||||
|
||||
Viewer Generation III
|
||||
|
||||
Split the API into the following sections:
|
||||
- main control actions
|
||||
do main domain tasks like image and ribbon manipulation.
|
||||
- serialization and deserialization
|
||||
load and save data
|
||||
- UI
|
||||
basic align, animation and modes
|
||||
|
||||
*/
|
||||
|
||||
function createImage(n){
|
||||
if(n == null){
|
||||
if(window._n == null){
|
||||
window._n = 0
|
||||
}
|
||||
n = _n
|
||||
_n += 1
|
||||
}
|
||||
return $('<div order="'+n+'" class="image"/>')
|
||||
}
|
||||
function createRibbon(){
|
||||
return $('<div class="ribbon"/>')
|
||||
}
|
||||
|
||||
|
||||
// NOTE: if this returns null, it means that the element is smallest in
|
||||
// target ribbon -- first position.
|
||||
function getImageBefore(image, ribbon){
|
||||
image = $(image)
|
||||
var images = $(ribbon).find('.image')
|
||||
var order = image.attr('order')
|
||||
var prev = null
|
||||
|
||||
images.each(function(){
|
||||
if(order < $(this).attr('order')){
|
||||
return false
|
||||
}
|
||||
prev = this
|
||||
})
|
||||
|
||||
return prev
|
||||
}
|
||||
|
||||
function shiftTo(image, ribbon){
|
||||
var target = getImageBefore(image, ribbon)
|
||||
var cur_ribbon = image.closest('.ribbon')
|
||||
|
||||
// insert before the first image if nothing is before the target...
|
||||
if(target == null){
|
||||
image.insertBefore($(ribbon).find('.image').first())
|
||||
|
||||
} else {
|
||||
image.insertAfter(target)
|
||||
}
|
||||
|
||||
// if removing last image out of a ribbon, remove the ribbon....
|
||||
if(cur_ribbon.find('.image').length == 0){
|
||||
cur_ribbon.remove()
|
||||
}
|
||||
|
||||
return image
|
||||
}
|
||||
|
||||
function shiftImage(direction, image, force_create_ribbon){
|
||||
if(image == null){
|
||||
// XXX need to make this context specific...
|
||||
image = $('.current.image')
|
||||
} else {
|
||||
image = $(image)
|
||||
}
|
||||
var ribbon = image.closest('.ribbon')[direction]('.ribbon')
|
||||
|
||||
// need to create a new ribbon...
|
||||
if(ribbon.length == 0 || force_create_ribbon == true){
|
||||
ribbon = createRibbon()['insert' + (direction == 'prev'
|
||||
? 'Before'
|
||||
: 'After')](image.closest('.ribbon'))
|
||||
ribbon.append(image)
|
||||
} else {
|
||||
shiftTo(image, ribbon)
|
||||
}
|
||||
return image
|
||||
}
|
||||
|
||||
// short-hand methods...
|
||||
function shiftImageUp(image){
|
||||
return shiftImage('prev', image)
|
||||
}
|
||||
function shiftImageDown(image){
|
||||
return shiftImage('next', image)
|
||||
}
|
||||
function shiftImageUpNewRibbon(image){
|
||||
return shiftImage('prev', image, true)
|
||||
}
|
||||
function shiftImageDownNewRibbon(image){
|
||||
return shiftImage('next', image, true)
|
||||
}
|
||||
|
||||
|
||||
// TODO manual image ordering (shiftLeft/shiftRight functions)
|
||||
// XXX
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// NOTE: this is on purpose done relative...
|
||||
function clickHandler(evt){
|
||||
var img = $(evt.target).closest('.image')
|
||||
img.closest('.viewer').find('.current.image').removeClass('current')
|
||||
img.addClass('current')
|
||||
}
|
||||
|
||||
// setup...
|
||||
$(function(){
|
||||
|
||||
// populate the viewer...
|
||||
var r = createRibbon()
|
||||
var images = []
|
||||
for(var i=0; i < 40; i++){
|
||||
images.push(createImage().text(i)[0])
|
||||
}
|
||||
r.append($(images))
|
||||
var rr = r.clone()
|
||||
var rrr = r.clone()
|
||||
|
||||
$('.ribbon-set')
|
||||
.append(r)
|
||||
.append(rr)
|
||||
.append(rrr)
|
||||
|
||||
// NOTE: this is global so as to not to add any extra complexity to
|
||||
// the internal workings...
|
||||
$('.viewer').click(clickHandler)
|
||||
|
||||
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<!-- This is the basic viewer structure...
|
||||
|
||||
Unpopulated
|
||||
NOTE: there can be only .ribbon-set element.
|
||||
|
||||
<div class="viewer">
|
||||
<div class="ribbon-set"></div>
|
||||
</div>
|
||||
|
||||
|
||||
Populated
|
||||
|
||||
<div class="viewer">
|
||||
<div class="ribbon-set">
|
||||
<div class="ribbon">
|
||||
<div class="image"></div>
|
||||
<div class="image"></div>
|
||||
</div>
|
||||
<div class="ribbon">
|
||||
<div class="image"></div>
|
||||
<div class="current image"></div>
|
||||
<div class="image"></div>
|
||||
<div class="image"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<div class="viewer">
|
||||
<div class="ribbon-set"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- vim:set ts=4 sw=4 spell : -->
|
||||
</body>
|
||||
</html>
|
||||
Loading…
x
Reference in New Issue
Block a user