Package qurtext.client

Source Code of qurtext.client.SectionView$ArabicWord

/* Copyright (C) Abu Rizal, 2009.
*
* This file is part of QurText.
*
* QurText 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.
*
* QurText 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 QurText. If not, see <http://www.gnu.org/licenses/>.
*/
package qurtext.client;

import java.util.ArrayList;
import java.util.TreeMap;
import java.util.TreeSet;

import com.allen_sauer.gwt.voices.client.Sound;
import com.allen_sauer.gwt.voices.client.SoundController;
import com.allen_sauer.gwt.voices.client.handler.PlaybackCompleteEvent;
import com.allen_sauer.gwt.voices.client.handler.SoundHandler;
import com.allen_sauer.gwt.voices.client.handler.SoundLoadStateChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.InlineHTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class SectionView extends BaseView {
  private static final int targetLinkCount=9; //total navigation links including jumps to ends.
  private static final int endLinkCount=2; //extra links to jump to the end
  private Hyperlink closeUpdateLink=new Hyperlink("Chapters","");
  private MainPresenter mainPresenter;

  private final Button initSectionButton=new Button("Initialize Section");
  private final Button initLiteralButton=new Button("Initialize Literals");
  private final Button reciteAllButton=new Button("Recite Section");
  private final Label sectionText=new Label("Click on a button!");

  private HorizontalPanel sectionNavigationBar=new HorizontalPanel();
  private final HorizontalPanel sectionPanel = new HorizontalPanel();
  private final HorizontalPanel sectionAdminBar = new HorizontalPanel();
  private VerticalPanel sectionMainPanel=new VerticalPanel();

    private SoundController soundController = new SoundController();
    private Sound sound;
    private String currentToken;
    private ArrayList<String> playList=new ArrayList<String>();
  private TreeMap<String,ArrayList<HTML>> textHtmlMap = new TreeMap<String, ArrayList<HTML>>();
  private TreeMap<String,HTML> translationHtmlMap = new TreeMap<String, HTML>();

  private SoundHandler soundHandler = new SoundHandler() {
   
    @Override
    public void onSoundLoadStateChange(SoundLoadStateChangeEvent event) {
      // do nothing
     
    }
   
    @Override
    public void onPlaybackComplete(PlaybackCompleteEvent event) {
      if (null==currentToken) return;
      ArrayList<HTML> textHtmls = textHtmlMap.get(currentToken);
      if (null==textHtmls) return;
      for (HTML textHTML:textHtmls) {
        textHTML.removeStyleName("selected");
      }
      HTML translationHtml = translationHtmlMap.get(currentToken);
      if (null==translationHtml) return;
      translationHtml.removeStyleName("selected");
      currentToken=null;
      sound=null;
      if (playList.size()>0) recite();
    }
  }
  private ClickHandler playAudioHandler=new ClickHandler() {

    @Override
    public void onClick(ClickEvent event) {
      HTML source=(HTML) event.getSource();
      String newToken = source.getElement().getAttribute("name").trim();
      playList.clear();
      playList.add(newToken);
      stopReciting();
      recite();
    }

  };

  private void stopReciting() {
    if (null!=sound) {
      sound.stop();
      soundHandler.onPlaybackComplete(null);
    }
  }

  private ClickHandler updateClickHandler = new ClickHandler() {

    @Override
    public void onClick(ClickEvent event) {
      Hyperlink sender=(Hyperlink)event.getSource();
      String historyToken = sender.getTargetHistoryToken();
      mainPresenter.handleHistoryToken(historyToken);
    }

  };
 
  public MainPresenter getMainPresenter() {
    return mainPresenter;
  }

  public void setMainPresenter(MainPresenter mainPresenter) {
    this.mainPresenter = mainPresenter;
  }

  public void showSection(ClientSection section) {
    mainPresenter.showSectionPanel();
   
    sectionNavigationBar.clear();
      sectionNavigationBar.add(closeUpdateLink);
      sectionNavigationBar.addStyleName("navbar");
    if (mainPresenter.getAllSections()==null) return; //not initialized yet
      int sectionNo = section.sectionNo;
      int start=0;
      int end=mainPresenter.getAllSections().size();
      if (sectionNo<=start+targetLinkCount/2) { //0 1 2 3 *4* 5 6 | 7 8
        end=start+(targetLinkCount-endLinkCount);
      } else if (sectionNo>=end-targetLinkCount/2) { //2 3 | 4 5 *6* 7 8 9 10
        start=end-(targetLinkCount-endLinkCount);
      } else {
        start = (sectionNo-(targetLinkCount/2-endLinkCount)); // 0 .. 3 4 *5* 6 7 .. 10
        end = (sectionNo+(targetLinkCount/2-endLinkCount)+1);
      }
      addPreviousSectionLink(section, sectionNo-1);
      if (start>0) {
        addSectionLink(section, 0);
      }
         if (start>1) {
        sectionNavigationBar.add(spacer());
        sectionNavigationBar.add(new HTML("..."));
      }
      for (int i=start;i<end;i++) {
        addSectionLink(section, i);
      }
       if (end<mainPresenter.getAllSections().size()-1) {
         sectionNavigationBar.add(spacer());
         sectionNavigationBar.add(new HTML("..."));
       }
       if (end<mainPresenter.getAllSections().size()) {
         addSectionLink(section, mainPresenter.getAllSections().size()-1);
       }
      addNextSectionLink(section, sectionNo+1);
      sectionNavigationBar.add(reciteAllButton);
  }

  private void addSectionLink(ClientSection currentSection, int i) {
    ClientSection section=mainPresenter.getAllSections().get(i);
    sectionNavigationBar.add(spacer());
    String label="" + section.verse;
    if (1==section.verse) label=""+section.chapter+":"+label;
    addSectionLink(currentSection, section, label);
  }

  private void addPreviousSectionLink(ClientSection currentSection, int i) {
    if (i<0) i=0;
    ClientSection section=mainPresenter.getAllSections().get(i);
    sectionNavigationBar.add(spacer());
    String label="<<";
    addSectionLink(currentSection, section, label);
  }

  private void addNextSectionLink(ClientSection currentSection, int i) {
    if (i>=mainPresenter.getAllSections().size()) i=mainPresenter.getAllSections().size()-1;
    ClientSection section=mainPresenter.getAllSections().get(i);
    sectionNavigationBar.add(spacer());
    String label=">>";
    addSectionLink(currentSection, section, label);
  }

  private Hyperlink addSectionLink(ClientSection currentSection,
      ClientSection section, String label) {
    Hyperlink sectionLink = null;
    if (currentSection.equals(section)) {
      sectionNavigationBar.add(new HTML("<b>" + label + "</b>"));
      mainPresenter.getSectionPresenter().updateSectionPanel(section);
    } else {
      sectionLink = new Hyperlink(label,"" + section.chapter + ":" + section.verse);
      sectionLink.addClickHandler(updateClickHandler);
      sectionNavigationBar.add(sectionLink);
    }
    return sectionLink;
  }

  /**
   * initialize all widgets for the first time
   */
  public void onSectionViewLoad() {
      closeUpdateLink.addClickHandler(new ClickHandler() {

      @Override
      public void onClick(ClickEvent event) {
        mainPresenter.showJumpPanel();
      }
      });
      initSectionButton.addClickHandler(new ClickHandler() {

      @Override
      public void onClick(ClickEvent event) {
        mainPresenter.getSectionPresenter().onInitSection();
      }
       
      });
      initLiteralButton.addClickHandler(new ClickHandler() {

      @Override
      public void onClick(ClickEvent event) {
        mainPresenter.getSectionPresenter().onInitLiteral();
      }

      });
      reciteAllButton.addClickHandler(new ClickHandler() {

      @Override
      public void onClick(ClickEvent event) {
        playList.clear();
        stopReciting();
        ClientSection section=mainPresenter.getCurrentSection();
        for (ClientVerse verse:section.verses.values()) {
          if (verse.verseNo==1 && verse.chapterNo!=1 && verse.chapterNo!=9) {
            playList.add("1:1");
          }
          playList.add("" + verse.chapterNo + ":" + verse.verseNo);
        }
        recite();
      }
      });
      sectionAdminBar.setVisible(false);
      sectionAdminBar.add(initSectionButton);
      sectionAdminBar.add(spacer());
      sectionAdminBar.add(initLiteralButton);
      sectionAdminBar.add(spacer());
      sectionAdminBar.add(sectionText);
      sectionAdminBar.setWidth("100%");
     
      sectionNavigationBar.setWidth("100%");
     
      sectionPanel.setWidth("100%");
      sectionMainPanel.setWidth("100%");
      sectionMainPanel.add(sectionAdminBar);
      sectionMainPanel.add(sectionNavigationBar);
      sectionMainPanel.add(sectionPanel);
  }

  public void sectionPanelClear() {
    sectionPanel.clear();
  }

  public void showText(TreeMap<Integer, ClientVerse> verses) {
    FlowPanel textPanel=new FlowPanel();
    textPanel.setWidth("600");
    textPanel.addStyleName("arabic");
    textPanel.getElement().setAttribute("dir", "rtl");
    int chapterNo = verses.values().iterator().next().chapterNo;
    showChapterArabicName(chapterNo, textPanel);

    for (ClientVerse verse:verses.values()) {
      if (verse.verseNo==1 && verse.chapterNo!=1 && verse.chapterNo!=9) {
        FlowPanel basmallahPanel=new FlowPanel();
        basmallahPanel.setWidth("100%");
        basmallahPanel.addStyleName("basmallah");
        showText(basmallahPanel, mainPresenter.getSectionPresenter().getBasmallah());
        textPanel.add(basmallahPanel);
      }
      showText(textPanel, verse);
      String token = "" + verse.chapterNo + ":" + verse.verseNo;
      InlineHTML number = new InlineHTML("<font color='gray'><sup><nobr>{" + arabicNumber(verse.verseNo) + "}</nobr></sup></font> ");
      addPlayRecitationHandler(token, number, true);
      textPanel.add(number);
    }
    sectionPanel.add(textPanel);
  }

  private boolean showChapterArabicName(int chapterNo,
      FlowPanel textPanel) {
    ClientChapter chapter=mainPresenter.getChapter(chapterNo);
    if (null==chapter) return false;
    textPanel.add(new HTML("\u0633\u0648\u0631\u0629 " + chapter.title));
    return true;
  }

  private String arabicNumber(int verseNo) {
    StringBuffer result=new StringBuffer();
    while (verseNo>0) {
      char c= (char) (1632+(verseNo % 10));
      result.insert(0, c);
      verseNo = verseNo / 10;
    }
    return result.toString();
  }

  private void addPlayRecitationHandler(String token, HTML widget, boolean showTitle) {
    widget.addClickHandler(playAudioHandler);
    if (showTitle) widget.setTitle("Click to recite");
    widget.getElement().setAttribute("name", token);
  }

  private static class ArabicWord {
    public String text;
    public String transliteration;
    public String literal;
    public String style;
  }
 
  private ArrayList<ArabicWord> getArabicWords(ClientVerse verse) {
    String[] arabicWords=rearrangeDiacritics(verse.text).split("[ ]");
    String[] transliterationWords=verse.transliteration.split("[ ]");
    String[] literalWords=htmlEscape(verse.literal).split("[ ]");
    ArrayList<ArabicWord> results = new ArrayList<ArabicWord>(arabicWords.length);
    int i=0;
    for (String word: arabicWords) {
      if ("".equals(word)) break; //unexpected empty word
      ArabicWord result=new ArabicWord();
      result.text=word;
     
      if (word.length()==1) {
        if ("\u06D6".compareTo(word)<=0 //ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA
          && "\u06DC".compareTo(word)>=0 //ARABIC ARABIC SMALL HIGH SEEN
          ) {
          result.style="sign";
        } else if ("\u06E9".equals(word) //ARABIC PLACE OF SAJDAH
            || "\u06DE".equals(word) //ARABIC START OF RUB EL HIZB
        ) {
          result.style="internal-sign";
        }
      } else {
        result.transliteration=transliterationWords[i];
        result.literal=literalWords[i];
        i++;
      }
     
      results.add(result);
    }
    return results;
  }

  /**
   * @param literal
   * @return
   */
  private String htmlEscape(String literal) {
    return literal.replaceAll("[<]","&lt;").replaceAll("[&]","&amp;");
  }
 
  private void showText(FlowPanel textPanel, ClientVerse verse) {
    if (null==verse) return;
    String arabicText = verse.text;
    if (null==arabicText) return;
    String token = "" + verse.chapterNo + ":" + verse.verseNo;
    ArrayList<ArabicWord> arabicWords=getArabicWords(verse);
    ArrayList<HTML> textHtmls = new ArrayList<HTML>(arabicWords.size());
    for (ArabicWord arabicWord:arabicWords) {
      InlineHTML text = new InlineHTML(arabicWord.text + " ");
      textHtmls.add(text);
      if (null==arabicWord.transliteration) {
        if (null!=arabicWord) text.addStyleName(arabicWord.style);
        addPlayRecitationHandler(token, text, true);
      } else {
        TooltipHandler handler=new TooltipHandler(arabicWord.transliteration.replaceAll("[<][s][>]","<font color='gray'><s>").replaceAll("[<][/][s][>]","</s></font>") + "<br/>" + arabicWord.literal, 10000, "tooltip");
        text.addMouseOverHandler(handler);
        text.addMouseOutHandler(handler);
        addPlayRecitationHandler(token, text, false);
      }
      textPanel.add(text);
    }
    textHtmlMap.put("" + verse.chapterNo + ":" + verse.verseNo,textHtmls);
  }

  /**
   * allow more readable rendering of arabic text, such as:
   * - KASRA and KASRATAN should be always under the base, instead of under the SHADDA
   * This is on best-effort basis. Some system might keep the KASRA under the SHADDA
   */
  private String rearrangeDiacritics(String text) {
    text = text.replaceAll("[\u0651][\u0650]", "\u0650\u0651"); // SHADDA KASRA
    text = text.replaceAll("[\u0651][\u064D]", "\u064D\u0651"); // SHADDA KASRATAN
    return text;
  }

  public void showTranslation(TreeMap<Integer, ClientVerse> verses) {
    FlowPanel textPanel=new FlowPanel();
    int chapterNo = verses.values().iterator().next().chapterNo;
    showChapterTranslationText(textPanel, chapterNo);
   
    TreeSet<String> topics=new TreeSet<String>();
    for (ClientVerse verse:verses.values()) {
      if (verse.verseNo==1 && verse.chapterNo!=1 && verse.chapterNo!=9) {
        ClientVerse basmallah = mainPresenter.getSectionPresenter().getBasmallah();
        if (null==basmallah) break;
        String token = "" + basmallah.chapterNo + ":" + basmallah.verseNo;
        String text = basmallah.translation + " ";
        InlineHTML translationHTML = new InlineHTML(text);
        translationHtmlMap.put(token, translationHTML);
        addPlayRecitationHandler(token, translationHTML, true);
        textPanel.add(translationHTML);
      }
      String token = "" + verse.chapterNo + ":" + verse.verseNo;
      InlineHTML number = new InlineHTML("<font color='gray'><sup>" + token + "</sup></font> ");
      addPlayRecitationHandler(token, number, true);
      textPanel.add(number);
      String text =verse.translation + " ";
      InlineHTML translationHTML = new InlineHTML(text);
      translationHtmlMap.put(token, translationHTML);
      addPlayRecitationHandler(token, translationHTML, true);
      textPanel.add(translationHTML);
      if (null!=verse.topics) {
        for (String topic:verse.topics.split("[,]")) {
          if (topic.length()>0) topics.add(topic);
        }
      }
    }
    textPanel.addStyleName("translation");
    StringBuffer topicString=new StringBuffer();
    for (String topic:topics) {
      topicString.append(topic);
      topicString.append(", ");
    }
    if (topicString.length()>0) topicString.setLength(topicString.length()-", ".length());
    textPanel.add(new HTML("Topics: " + topicString));
    sectionPanel.add(textPanel);
  }

  private boolean showChapterTranslationText(FlowPanel textPanel, int chapterNo) {
    ClientChapter chapter=mainPresenter.getChapter(chapterNo);
    if (null==chapter) return false;
    textPanel.add(new HTML("Chapter " + chapterNo + ": " + chapter.transliteration));
    return true;
  }

  public void setStatusText(String text) {
    sectionText.setText(text);
  }

  public void showAdminTab() {
    sectionAdminBar.setVisible(true);
    initSectionButton.setVisible(true);
    initLiteralButton.setVisible(true);
    sectionText.setVisible(true);
  }

  public Widget getPanel() {
    return sectionMainPanel;
  }

  private void recite() {
    if (playList.size()<=0) return;
    currentToken = playList.remove(0);
    String[] tokens=currentToken.split("[:]");
    String filename = "000".substring(tokens[0].length())+tokens[0] + "000".substring(tokens[1].length())+tokens[1] + ".mp3";
    sound = soundController.createSound(Sound.MIME_TYPE_AUDIO_MPEG,
        "media/"+filename);
    sound.addEventHandler(soundHandler);
    sound.play();
    ArrayList<HTML> textHtmls = textHtmlMap.get(currentToken);
    if (null==textHtmls) return;
    for (HTML textHTML:textHtmls) {
      textHTML.addStyleName("selected");
    }
    HTML translationHtml = translationHtmlMap.get(currentToken);
    if (null==translationHtml) return;
    translationHtml.addStyleName("selected");
  }

}
TOP

Related Classes of qurtext.client.SectionView$ArabicWord

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.