Laureline's Wiki

Laureline's Wiki

Liseuse

Liseuse

Liseuse

La liseuse permet de lire les différents volumes de la bibliothèque. Elle est à part de le bibliothèque et ne fait que prendre un volume en entrée. Elle offre à l'utilisateur plusieurs option de navigation telle que:

  • Changer le sens de lecture: Cela permet, pour certains mangas, de lire de droite à gauche plutôt que de gauche à droite. Cela est surtout pratique quand on utilise les doubles pages.
  • Simple ou double pages: Cela gère l'affichage et définit si une seule page à la fois ou deux pages en même temps doivent être affichées. L'affichage de deux pages simultanées simule l'expérience qu'un utilisateur pourrait avoir si il lisait un livre physique.
  • Redimmensionnement de la page: Il est possible de définir le redimmensionnement automatique de la page sois sur la hauteur, sois sur la largeur de la fenêtre.

L'implémentation de la logique de la liseuse est faites grâce à un Navigator implémenté dans le package navigation. La classe Navigator étant abstraite, elle donne la possibilité de créer des Navigator pour un nombre de pages voulu. Nous avons décidé de ne l'implémenter que pour les pages simple (SimpleNavigator) et pour les pages doubles, c'est à dire 2 pages simples (DoubleNavigator) car cela n'a pas de sens dans notre contexte de l'utiliser pour plus de pages.

Chaque Navigator contient un volume et une page courante qui est affichée. Ces pages sont définie au tant que DisplayPage, qui est aussi une classe abstraite permettant d'implémenter des classes définies sur un nombre de pages voulu. Nous avons implémenté les classes pour des pages simples (SimplePage) et des pages double, c'est à dire 2 pages simples (DoublePage). Une fois encore, nous n'avons pas implémenté d'autre classe, cela n'ayant pas de sens pour nous mais cela serait tout à fait possible.

En résumé, le Navigator permet d'implémenter la logique par laquelle les pages doivent être parcourues alors que les DisplayPage permettent simplement de contenir une page de manière contrôlée et définie dans le programme.

Voici un diagramme de classe pour le Navigator:

<uml> hide empty fields hide empty methods

abstract class Navigator{

  1. vol: Volume
  2. direction: Direction
  3. currentPage: DisplayPage

+setDirection(sens: Direction) : void

+setCurrentPage(page: DisplayPage) : void
+getVolume() : Volume
+getDirection(): Direction
+getCurrentPage(): DisplayPage

} class SimpleNavigator {

+SimpleNavigator(volume: Volume, direction: Direction, beginIndex: Int)
+SimpleNavigator(nav: DoubleNavigator)
+nextPages(): DisplayPage
+previousPages(): DisplayPage
+goTo(index: int): DisplayPage

} class DoubleNavigator {

+DoubleNavigator(volume: Volume, direction: Direction, beginIndex: Int)
+DoubleNavigator(nav: SimpleNavigator)
+update(): void
+nextPages(): DisplayPage
+previousPages(): DisplayPage
+goTo(index: int): DisplayPage

} interface INavigator {

+nextPages() : DisplayPage
+previousPages() : DisplayPage
+goTo(index: int): DisplayPage
+setDirection(sens: Direction) : void
+setCurrentPage(page: DisplayPage) : void
+getVolume() : Volume
+getDirection(): Direction
+getCurrentPage(): DisplayPage

}

enum Direction{

LTR,RTL

}

Navigator –> SimpleNavigator Navigator –> DoubleNavigator INavigator –> Navigator </uml>

On peut voir que l'on utilise une interface INavigator qui oblige les implémentations de définir les méthodes essentielles à la logique d'un navigateur. Le Navigator implémente partiellement certaines méthodes qui sont communes à n'importe quel navigateur.

Voici un diagramme de classe pour le DisplayPage: <uml> hide empty fields hide empty methods

abstract class DisplayPage{

  1. imageIndexes: ArrayList<Integer>
  2. imageReferences: ArrayList<Image>
  3. direction: Direction

+DisplayPage(indexes: ArrayList<Integer>, images: ArrayList<Image>, dir: Direction)

+getImageIndexes(): ArrayList<Integer>
+getImageReferences(): ArrayList<Image>
+getDirection(): Direction

} class SinglePage {

+SinglePage(index: int, image: Image, dir: Direction)
+getImage(): Image
+getIndex(): int

} class DoublePage {

+DoublePage(index1: int, index2: int, image1: Image, image2: Image, dir: Direction)
+getFirstImage(): Image
+getSecondeImage(): Image
+getFirstIndex(): int
+getSecondIndex(): int

} interface IDisplayPage {

+getImageIndexes(): ArrayList<Integer>
+getImageReferences(): ArrayList<Image>
+getDirection(): Direction

}

DisplayPage –> SinglePage DisplayPage –> DoublePage IDisplayPage –> DisplayPage </uml>

Ici, la logique est la même que pour le navigateur. Une interface définissant les méthodes obligatoires et une classe DisplayPage qui permet de faire une implémentation partielle des pages.

Une subtilité réside dans le DoubleNavigator. En effet, il est possible que des page doubles, c'est à dire des pages qui, dans un livre physique sont en paysage, se trouvent dans le volume. Ces pages ont été mises par les gens qui ont numérisé le livre comme une grande page qui est plus large que haute. Cela a été fait pour conserver le travail de l'auteur et ne pas dénaturer ces images en les séparant sur deux pages différentes. Dans ce cas, si jamais le DoubleNavigator voit qu'il y'a une double page, il va uniquement afficher la prochaine page et non les 2 prochaines pages. Cela à pour effet que la page courante dans le navigateur sera une SimplePage et non une DoublePage comme on pourrait s'y attendre. Avec ce système, la vue n'a pas à ce soucier du type de navigateur qu'elle utilise, étant donné qu'elle reçoit une DisplayPage et de ce fait, il lui suffit de faire un contrôle du type de page qu'elle a pour donner le bon affichage.

Exemple d'image simple

Exemple d'image double

Redimensionnement

La liseuse offre trois options de redimensionnement: Complet, Horizontal, Vertical. Le mode complet affiche la/les page(s) courante(s) au complet sur la fenêtre. Le redimensionnement Horizontal agrandi l'image jusqu'à ce que sa largeur soit celle de la fenêtre, l'utilisateur peut alors faire défiler l'image verticalement. De même, le mode vertical effectue un redimensionnement par rapport à la hauteur de l'image.

La logique est implémentée dans la fonction ReaderController#refreshScaling() qui prend en charge tout les modes ainsi que le mode simple et double page. Cette fonction est appellée quand l'utilisateur change les dimensions de la fenêtre et lors d'un changement de page.