Improve RTL layout behaviour and fix its display.

This commit is contained in:
Ghazi Triki 2018-07-22 14:45:18 +01:00
parent f536467879
commit 7f96487eba
10 changed files with 325 additions and 41 deletions

View File

@ -15,7 +15,7 @@
<locale code="nl_NL" name="Dutch" native="Nederlands"/>
<locale code="en_US" name="English" native="English"/>
<locale code="et_EE" name="Estonian" native="Eesti"/>
<locale code="fa_IR" name="Farsi" native="فارسى"/>
<locale code="fa_IR" name="Farsi" native="فارسى" direction="rtl"/>
<locale code="fi_FI" name="Finnish" native="Suomi"/>
<locale code="fr_FR" name="French" native="Français"/>
<locale code="fr_CA" name="French (Canadian)" native="Français (Canadien)"/>

View File

@ -19,9 +19,10 @@ You should have received a copy of the GNU Lesser General Public License along
with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-->
<mx:Application xmlns:mx="library://ns.adobe.com/flex/mx"
<BigBlueButtonApplication xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:views="*"
xmlns="org.bigbluebutton.core.*"
xmlns:logging="org.bigbluebutton.common.logging.*"
pageTitle="BigBlueButton"
layout="absolute"
@ -54,4 +55,4 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
<views:BigBlueButtonMainContainer id="bbbShell"/>
</mx:Application>
</BigBlueButtonApplication>

View File

@ -0,0 +1,25 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core {
import mx.core.Application;
[Frame(factoryClass = "org.bigbluebutton.core.managers.SystemManager")]
public class BigBlueButtonApplication extends Application {
}
}

View File

@ -56,9 +56,8 @@ package org.bigbluebutton.core.managers {
var date:Date = new Date();
var localeReqURL:String = buildRequestURL();
trace("::loadConfig [{0}]", [localeReqURL]);
trace(localeReqURL + " session=[" + sessionToken + "]");
LOGGER.debug("loadConfig request={0} session=[{1}]", [localeReqURL, sessionToken]);
var request:URLRequest = new URLRequest(localeReqURL);
request.method = URLRequestMethod.GET;
@ -75,21 +74,19 @@ package org.bigbluebutton.core.managers {
}
private function handleComplete(e:Event):void {
trace("handleComplete [{0}]", [new XML(e.target.data)]);
LOGGER.debug("handleComplete [{0}]", [new XML(e.target.data)]);
var xml:XML = new XML(e.target.data)
var dispatcher:Dispatcher = new Dispatcher();
if (xml.returncode == "FAILED") {
// trace("Getting configXML failed [{0}]", [xml]);
LOGGER.error("Getting configXML failed [{0}]", [xml]);
dispatcher.dispatchEvent(new MeetingNotFoundEvent(xml.response.logoutURL));
} else {
// trace("Getting configXML passed [{0}]", [xml]);
LOGGER.info("Getting configXML passed [{0}]", [xml]);
_config = new Config(new XML(e.target.data));
trace("Initializing logging.");
LOGGER.debug("Initializing logging.");
LogUtil.initLogging();
dispatcher.dispatchEvent(new ConfigLoadedEvent());

View File

@ -0,0 +1,187 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.managers {
import flash.display.DisplayObject;
import flash.geom.Point;
import flash.geom.Rectangle;
import mx.core.FlexVersion;
import mx.core.IFlexDisplayObject;
import mx.core.IInvalidating;
import mx.core.UIComponent;
import mx.core.mx_internal;
import mx.events.Request;
import mx.managers.IPopUpManager;
import mx.managers.ISystemManager;
import mx.managers.PopUpData;
import mx.managers.PopUpManagerImpl;
use namespace mx_internal;
public class PopUpManagerImpl extends mx.managers.PopUpManagerImpl {
/**
* @private
*/
private static var instance:IPopUpManager;
/**
* @private
*/
public static function getInstance():IPopUpManager {
if (!instance)
instance = new org.bigbluebutton.core.managers.PopUpManagerImpl();
return instance;
}
/**
* Centers a popup window over whatever window was used in the call
* to the <code>createPopUp()</code> or <code>addPopUp()</code> method.
*
* <p>Note that the position of the popup window may not
* change immediately after this call since Flex may wait to measure and layout the
* popup window before centering it.</p>
*
* @param The IFlexDisplayObject representing the popup.
*
* @langversion 3.0
* @playerversion Flash 9
* @playerversion AIR 1.1
* @productversion Flex 3
*/
override public function centerPopUp(popUp:IFlexDisplayObject):void {
if (popUp is IInvalidating)
IInvalidating(popUp).validateNow();
const o:PopUpData = findPopupInfoByOwner(popUp);
// If we don't find the pop owner or if the owner's parent is not specified or is not on the
// stage, then center based on the popUp's current parent.
var popUpParent:DisplayObject = (o && o.parent && o.parent.stage) ? o.parent : popUp.parent;
if (popUpParent) {
//FLEX-28967 : https://issues.apache.org/jira/browse/FLEX-28967. Fix by miroslav.havrlent
var systemManager:ISystemManager;
if (o != null) {
systemManager = o.systemManager;
} else if (popUpParent.hasOwnProperty("systemManager")) {
systemManager = popUpParent["systemManager"];
} else if (popUpParent is ISystemManager) {
systemManager = popUpParent as ISystemManager;
}
if (!systemManager)
return; // or throw exception maybe ?
var x:Number;
var y:Number;
var appWidth:Number;
var appHeight:Number;
var parentWidth:Number;
var parentHeight:Number;
var rect:Rectangle;
var clippingOffset:Point = new Point();
var pt:Point;
var isTopLevelRoot:Boolean;
var sbRoot:DisplayObject = systemManager.getSandboxRoot();
var request:Request;
if (hasEventListener("isTopLevelRoot")) {
request = new Request("isTopLevelRoot", false, true);
}
if (request && !dispatchEvent(request))
isTopLevelRoot = Boolean(request.value);
else
isTopLevelRoot = systemManager.isTopLevelRoot();
if (isTopLevelRoot && (FlexVersion.compatibilityVersion < FlexVersion.VERSION_4_6)) {
// The sandbox root is the top level root.
// The application width is just the screen width.
var screen:Rectangle = systemManager.screen;
appWidth = screen.width;
appHeight = screen.height;
} else {
rect = systemManager.getVisibleApplicationRect();
rect.topLeft = DisplayObject(systemManager).globalToLocal(rect.topLeft);
rect.bottomRight = DisplayObject(systemManager).globalToLocal(rect.bottomRight);
// Offset the top, left of the window to bring it into view.
clippingOffset = rect.topLeft.clone();
appWidth = rect.width;
appHeight = rect.height;
}
// If parent is a UIComponent, check for clipping between
// the object and its SystemManager
if (popUpParent is UIComponent) {
rect = UIComponent(popUpParent).getVisibleRect();
if (UIComponent(popUpParent).systemManager != sbRoot)
rect = UIComponent(popUpParent).systemManager.getVisibleApplicationRect(rect);
var offset:Point = popUpParent.globalToLocal(rect.topLeft);
clippingOffset.x += offset.x;
clippingOffset.y += offset.y;
parentWidth = rect.width;
parentHeight = rect.height;
} else {
parentWidth = popUpParent.width;
parentHeight = popUpParent.height;
}
// The appWidth may smaller than parentWidth if the application is
// clipped by the parent application.
x = Math.max(0, (Math.min(appWidth, parentWidth) - popUp.width) / 2);
y = Math.max(0, (Math.min(appHeight, parentHeight) - popUp.height) / 2);
// If the layout has been mirrored, then 0,0 is the uppper
// right corner; compensate here.
// Code removed below, centring a popup does not need RTL layou check
pt = new Point(clippingOffset.x, clippingOffset.y);
pt = popUpParent.localToGlobal(pt);
pt = popUp.parent.globalToLocal(pt);
popUp.move(Math.round(x) + pt.x, Math.round(y) + pt.y);
}
}
/**
* @private
* Returns the index position of the PopUpData in the popupInfo array (or -1)
* for a given popupInfo.owner
*/
private function findPopupInfoIndexByOwner(owner:Object):int {
const n:int = popupInfo.length;
for (var i:int = 0; i < n; i++) {
var o:PopUpData = popupInfo[i];
if (o.owner == owner)
return i;
}
return -1;
}
/**
* @private
* Returns the PopUpData (or null) for a given popupInfo.owner
*/
private function findPopupInfoByOwner(owner:Object):PopUpData {
var index:int = findPopupInfoIndexByOwner(owner);
return index > -1 ? popupInfo[index] : null;
}
}
}

View File

@ -0,0 +1,34 @@
/**
* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
*
* Copyright (c) 2018 BigBlueButton Inc. and by respective authors (see below).
*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free Software
* Foundation; either version 3.0 of the License, or (at your option) any later
* version.
*
* BigBlueButton 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
*
*/
package org.bigbluebutton.core.managers {
import mx.core.Singleton;
import mx.core.mx_internal;
import mx.managers.SystemManager;
use namespace mx_internal;
public class SystemManager extends mx.managers.SystemManager {
override mx_internal function kickOff():void {
if (document)
return;
Singleton.registerClass("mx.managers::IPopUpManager", PopUpManagerImpl);
super.kickOff();
}
}
}

View File

@ -42,7 +42,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function changeLanguage():void {
ResourceUtil.getInstance().setPreferredLocale(selectedItem);
ResourceUtil.getInstance().setPreferredLocale(selectedItem.code);
}
]]>
</fx:Script>

View File

@ -109,6 +109,8 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import mx.core.UIComponent;
import mx.events.FlexEvent;
import flashx.textLayout.formats.Direction;
import flexlib.mdi.effects.effectsLib.MDIVistaEffects;
import org.as3commons.lang.StringUtils;
@ -164,6 +166,10 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
import org.bigbluebutton.util.browser.BrowserCheck;
import org.bigbluebutton.util.i18n.ResourceUtil;
private static const LOGGER:ILogger = getClassLogger(MainApplicationShell);
private var globalDispatcher:Dispatcher;
@ -225,6 +231,9 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
public function initOptions(e:Event):void {
// Set the layout direction at the application start
ResourceUtil.getInstance().updateLayoutDirection();
brandingOptions = Options.getOptions(BrandingOptions) as BrandingOptions;
layoutOptions = Options.getOptions(LayoutOptions) as LayoutOptions;
usersOptions = Options.getOptions(UsersOptions) as UsersOptions;
@ -414,7 +423,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
guestWindow = PopUpUtil.createModalPopUp( FlexGlobals.topLevelApplication as DisplayObject, GuestWindow, false) as GuestWindow;
PopUpUtil.lockPosition(guestWindow, function():Point {
return new Point(systemManager.screen.width - guestWindow.width - 20, 20);
if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) {
return new Point(20, 20);
} else {
return new Point(systemManager.screen.width - guestWindow.width - 20, 20);
}
});
guestWindow.addEventListener(Event.CLOSE, closeGuestWindow);
@ -856,7 +869,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
var popUp:RecordWindow = PopUpUtil.createModalPopUp(FlexGlobals.topLevelApplication as DisplayObject, RecordWindow, false) as RecordWindow;
popUp.setRecordingFlag(e.payload.recording);
PopUpUtil.lockPosition(popUp, function():Point {
return new Point(parentApplication.width - 150 - popUp.width, y + toolbar.height);
if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) {
return new Point(150, y + toolbar.height);
} else {
return new Point(parentApplication.width - popUp.width - 150, y + toolbar.height);
}
});
}
@ -877,9 +894,6 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
}
private function onLocaleChanged(e:LocaleChangeEvent) : void {
if (ResourceUtil.getInstance().isRTLEnabled()) {
FlexGlobals.topLevelApplication.setStyle("layoutDirection", ResourceUtil.getInstance().getCurrentLanguageDirection());
}
PopUpUtil.initAlert();
}

View File

@ -345,7 +345,11 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
// Needs to be improved in case of RTL layout
PopUpUtil.lockPosition(logoutWindow, function():Point {
return new Point(width - logoutWindow.width - 5, btnLogout.y + btnLogout.height + 5)
if (ResourceUtil.getInstance().isRTLEnabled() && ResourceUtil.getInstance().getCurrentLanguageDirection() == Direction.RTL) {
return new Point(5, btnLogout.y + btnLogout.height + 5)
} else {
return new Point(width - logoutWindow.width - 5, btnLogout.y + btnLogout.height + 5)
}
});
} else {
doLogout();

View File

@ -102,11 +102,11 @@ package org.bigbluebutton.util.i18n
preferredLocale = getDefaultLocale();
if (preferredLocale != MASTER_LOCALE) {
trace("Preferred locale=" + preferredLocale + " is not the same as master locale=" + MASTER_LOCALE);
LOGGER.debug("Preferred locale={0} is not the same as master locale={1}", [preferredLocale, MASTER_LOCALE]);
loadMasterLocale(MASTER_LOCALE);
}
// To improve
setPreferredLocale({code:preferredLocale, direction:"ltr"});
setPreferredLocale(preferredLocale);
}
private function parse(xml:XML):void{
@ -134,12 +134,25 @@ package org.bigbluebutton.util.i18n
return ExternalInterface.call("getLanguage");
}
private function isPreferredLocaleAvailable(prefLocale:String):Boolean {
for each(var item:* in locales) {
private function findPreferredLocale(prefLocale:String) : * {
var item:* = null;
// Lookginf for locale in format 'en_US'
for each(item in locales) {
if (prefLocale == item.code)
return true;
return item;
}
return false;
// If not found we look for form 'en'
var mainLocale : String = prefLocale.substr(0,2);
for each(item in locales) {
if (mainLocale == item.code)
return item;
}
// If not found we look for the first item that contains 'en'
for each(item in locales) {
if (StringUtils.startsWith(item.code, mainLocale))
return item;
}
return null;
}
private function getIndexForLocale(prefLocale:String):int {
@ -150,19 +163,21 @@ package org.bigbluebutton.util.i18n
return -1;
}
public function setPreferredLocale(locale:Object):void {
var localeCode : String = locale.code;
public function setPreferredLocale(locale:String):void {
var localeCode : String = locale;
if (localeCode == DEFAULT_LOCALE_IDENTIFIER) {
localeCode = getDefaultLocale();
}
if (isPreferredLocaleAvailable(localeCode)) {
preferredLocale = localeCode;
}else{
var foundLocale : Object = findPreferredLocale(localeCode);
if (foundLocale) {
preferredLocale = foundLocale.code;
preferredDirection = foundLocale.direction;
} else {
preferredLocale = MASTER_LOCALE;
preferredDirection = "ltr";
}
preferredDirection = locale.direction;
changeLocale(preferredLocale);
}
@ -184,7 +199,7 @@ package org.bigbluebutton.util.i18n
}
private function loadMasterLocale(locale:String):void {
trace("Loading master locale=" + locale);
LOGGER.debug("Loading master locale={0}", [locale]);
/**
* http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/resources/IResourceManager.html#localeChain
* Always load the default language, so if the chosen language
@ -195,10 +210,10 @@ package org.bigbluebutton.util.i18n
}
private function onMasterLocaleLoaded(event:ResourceEvent):void {
trace("Master locale is loaded");
LOGGER.debug("Master locale is loaded");
masterLocaleLoaded = true;
if (masterLocaleLoadedCallback != null) {
trace("Calling callback to load a second language");
LOGGER.debug("Calling callback to load a second language");
masterLocaleLoadedCallback();
}
}
@ -208,7 +223,7 @@ package org.bigbluebutton.util.i18n
var date:Date = new Date();
var localeURI:String = buildRequestURL() + 'client/locale/' + language + '_resources.swf?a=' + date.time;
trace("Loading locale " + localeURI);
LOGGER.debug("Loading locale {0}", [localeURI]);
return resourceManager.loadResourceModule( localeURI, false);
}
@ -227,10 +242,10 @@ package org.bigbluebutton.util.i18n
public function changeLocale(locale:String):void {
if (masterLocaleLoaded || locale == MASTER_LOCALE) {
trace("Loading immediately " + locale);
LOGGER.debug("Loading immediately {0}", [locale]);
changeLocaleHelper(locale);
} else {
trace("Registering callback to load " + locale + " later");
LOGGER.debug("Registering callback to load {0} later", [locale]);
masterLocaleLoadedCallback = function():void {
changeLocaleHelper(locale);
}
@ -246,7 +261,7 @@ package org.bigbluebutton.util.i18n
var logData:Object = UsersUtil.initLogData();
logData.tags = ["locale"];
logData.message = "Failed to load locale = " + preferredLocale;
trace(JSON.stringify(logData));
LOGGER.debug(JSON.stringify(logData));
}
masterLocaleLoaded = true;
resourceManager.localeChain = [MASTER_LOCALE];
@ -257,7 +272,7 @@ package org.bigbluebutton.util.i18n
}
private function sendAppAndLocaleVersions():void {
trace("Sending locale version");
LOGGER.debug("Sending locale version");
var dispatcher:Dispatcher = new Dispatcher();
var versionEvent:AppVersionEvent = new AppVersionEvent();
versionEvent.configLocaleVersion = false;
@ -269,7 +284,7 @@ package org.bigbluebutton.util.i18n
* @param event
*/
private function handleResourceNotLoaded(event:ResourceEvent):void {
trace("Resource locale [" + preferredLocale + "] could not be loaded.");
LOGGER.debug("Resource locale {0} could not be loaded.", [preferredLocale]);
resourceManager.localeChain = [MASTER_LOCALE];
preferredLocale = MASTER_LOCALE;
update();
@ -278,11 +293,18 @@ package org.bigbluebutton.util.i18n
public function update():void{
reloadLocaleNames();
sendAppAndLocaleVersions();
updateLayoutDirection();
var dispatcher:Dispatcher = new Dispatcher;
dispatcher.dispatchEvent(new LocaleChangeEvent(LocaleChangeEvent.LOCALE_CHANGED));
dispatchEvent(new Event(Event.CHANGE));
}
public function updateLayoutDirection():void {
if (isRTLEnabled()) {
FlexGlobals.topLevelApplication.setStyle("layoutDirection", preferredDirection);
}
}
[Bindable("change")]
public function getString(resourceName:String, parameters:Array = null, locale:String = null):String{
/**