Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f25e1e90 authored by Jason Chang's avatar Jason Chang
Browse files

(1/n) Phase out FEATURE_ONE_HANDED_BACKGROUND_PANEL

Remove DisplayArea feature FEATURE_ONE_HANDED_BACKGROUND_PANEL
We are going implement One handed panel throught
WindowlessWindow mechanism instead.

Bug: 197165590

Test: manually test One-handed mode basic operations.
Test: atest WMShellUnitTests
Change-Id: I3ba106a266e69bf61cdd43c0043852eed14dc365
parent f2af4d99
Loading
Loading
Loading
Loading
+1 −9
Original line number Diff line number Diff line
@@ -100,14 +100,6 @@ public class DisplayAreaOrganizer extends WindowOrganizer {
     */
    public static final int FEATURE_IME_PLACEHOLDER = FEATURE_SYSTEM_FIRST + 7;

    /**
     * Display area for one handed background layer, which preventing when user
     * turning the Dark theme on, they can not clearly identify the screen has entered
     * one handed mode.
     * @hide
     */
    public static final int FEATURE_ONE_HANDED_BACKGROUND_PANEL = FEATURE_SYSTEM_FIRST + 8;

    /**
     * Display area hosting IME window tokens (@see ImeContainer). By default, IMEs are parented
     * to FEATURE_IME_PLACEHOLDER but can be reparented under other RootDisplayArea.
@@ -118,7 +110,7 @@ public class DisplayAreaOrganizer extends WindowOrganizer {
     * app on another screen).
     * @hide
     */
    public static final int FEATURE_IME = FEATURE_SYSTEM_FIRST + 9;
    public static final int FEATURE_IME = FEATURE_SYSTEM_FIRST + 8;

    /**
     * The last boundary of display area for system features
+0 −272
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell.onehanded;

import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.view.ContextThemeWrapper;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.animation.LinearInterpolator;
import android.window.DisplayAreaAppearedInfo;
import android.window.DisplayAreaInfo;
import android.window.DisplayAreaOrganizer;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.android.wm.shell.R;
import com.android.wm.shell.common.DisplayLayout;

import java.io.PrintWriter;
import java.util.List;
import java.util.concurrent.Executor;

/**
 * Manages OneHanded color background layer areas.
 * To avoid when turning the Dark theme on, users can not clearly identify
 * the screen has entered one handed mode.
 */
public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer
        implements OneHandedAnimationCallback, OneHandedState.OnStateChangedListener {
    private static final String TAG = "OneHandedBackgroundPanelOrganizer";
    private static final int THEME_COLOR_OFFSET = 10;
    private static final int ALPHA_ANIMATION_DURATION = 200;

    private final Context mContext;
    private final SurfaceSession mSurfaceSession = new SurfaceSession();
    private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory
            mTransactionFactory;

    private @OneHandedState.State int mCurrentState;
    private ValueAnimator mAlphaAnimator;

    private float mTranslationFraction;
    private float[] mThemeColor;

    /**
     * The background to distinguish the boundary of translated windows and empty region when
     * one handed mode triggered.
     */
    private Rect mBkgBounds;
    private Rect mStableInsets;

    @Nullable
    @VisibleForTesting
    SurfaceControl mBackgroundSurface;
    @Nullable
    private SurfaceControl mParentLeash;

    public OneHandedBackgroundPanelOrganizer(Context context, DisplayLayout displayLayout,
            OneHandedSettingsUtil settingsUtil, Executor executor) {
        super(executor);
        mContext = context;
        mTranslationFraction = settingsUtil.getTranslationFraction(context);
        mTransactionFactory = SurfaceControl.Transaction::new;
        updateThemeColors();
    }

    @Override
    public void onDisplayAreaAppeared(@NonNull DisplayAreaInfo displayAreaInfo,
            @NonNull SurfaceControl leash) {
        mParentLeash = leash;
    }

    @Override
    public List<DisplayAreaAppearedInfo> registerOrganizer(int displayAreaFeature) {
        final List<DisplayAreaAppearedInfo> displayAreaInfos;
        displayAreaInfos = super.registerOrganizer(displayAreaFeature);
        for (int i = 0; i < displayAreaInfos.size(); i++) {
            final DisplayAreaAppearedInfo info = displayAreaInfos.get(i);
            onDisplayAreaAppeared(info.getDisplayAreaInfo(), info.getLeash());
        }
        return displayAreaInfos;
    }

    @Override
    public void unregisterOrganizer() {
        super.unregisterOrganizer();
        removeBackgroundPanelLayer();
        mParentLeash = null;
    }

    @Override
    public void onAnimationUpdate(SurfaceControl.Transaction tx, float xPos, float yPos) {
        final int yTopPos = (mStableInsets.top - mBkgBounds.height()) + Math.round(yPos);
        tx.setPosition(mBackgroundSurface, 0, yTopPos);
    }

    @Nullable
    @VisibleForTesting
    boolean isRegistered() {
        return mParentLeash != null;
    }

    void createBackgroundSurface() {
        mBackgroundSurface = new SurfaceControl.Builder(mSurfaceSession)
                .setBufferSize(mBkgBounds.width(), mBkgBounds.height())
                .setColorLayer()
                .setFormat(PixelFormat.RGB_888)
                .setOpaque(true)
                .setName("one-handed-background-panel")
                .setCallsite("OneHandedBackgroundPanelOrganizer")
                .build();

        // TODO(185890335) Avoid Dimming for mid-range luminance wallpapers flash.
        mAlphaAnimator = ValueAnimator.ofFloat(1.0f, 0.0f);
        mAlphaAnimator.setInterpolator(new LinearInterpolator());
        mAlphaAnimator.setDuration(ALPHA_ANIMATION_DURATION);
        mAlphaAnimator.addUpdateListener(
                animator -> detachBackgroundFromParent(animator));
    }

    void detachBackgroundFromParent(ValueAnimator animator) {
        if (mBackgroundSurface == null || mParentLeash == null) {
            return;
        }
        // TODO(185890335) Avoid Dimming for mid-range luminance wallpapers flash.
        final float currentValue = (float) animator.getAnimatedValue();
        final SurfaceControl.Transaction tx = mTransactionFactory.getTransaction();
        if (currentValue == 0.0f) {
            tx.reparent(mBackgroundSurface, null).apply();
        } else {
            tx.setAlpha(mBackgroundSurface, (float) animator.getAnimatedValue()).apply();
        }
    }

    /**
     * Called when onDisplayAdded() or onDisplayRemoved() callback.
     *
     * @param displayLayout The latest {@link DisplayLayout} representing current displayId
     */
    public void onDisplayChanged(DisplayLayout displayLayout) {
        mStableInsets = displayLayout.stableInsets();
        // Ensure the mBkgBounds is portrait, due to OHM only support on portrait
        if (displayLayout.height() > displayLayout.width()) {
            mBkgBounds = new Rect(0, 0, displayLayout.width(),
                    Math.round(displayLayout.height() * mTranslationFraction) + mStableInsets.top);
        } else {
            mBkgBounds = new Rect(0, 0, displayLayout.height(),
                    Math.round(displayLayout.width() * mTranslationFraction) + mStableInsets.top);
        }
    }

    @VisibleForTesting
    void onStart() {
        if (mBackgroundSurface == null) {
            createBackgroundSurface();
        }
        showBackgroundPanelLayer();
    }

    /**
     * Called when transition finished.
     */
    public void onStopFinished() {
        if (mAlphaAnimator == null) {
            return;
        }
        mAlphaAnimator.start();
    }

    @VisibleForTesting
    void showBackgroundPanelLayer() {
        if (mParentLeash == null) {
            return;
        }

        if (mBackgroundSurface == null) {
            createBackgroundSurface();
        }

        // TODO(185890335) Avoid Dimming for mid-range luminance wallpapers flash.
        if (mAlphaAnimator.isRunning()) {
            mAlphaAnimator.end();
        }

        mTransactionFactory.getTransaction()
                .reparent(mBackgroundSurface, mParentLeash)
                .setAlpha(mBackgroundSurface, 1.0f)
                .setLayer(mBackgroundSurface, -1 /* at bottom-most layer */)
                .setColor(mBackgroundSurface, mThemeColor)
                .show(mBackgroundSurface)
                .apply();
    }

    @VisibleForTesting
    void removeBackgroundPanelLayer() {
        if (mBackgroundSurface == null) {
            return;
        }

        mTransactionFactory.getTransaction()
                .remove(mBackgroundSurface)
                .apply();
        mBackgroundSurface = null;
    }

    /**
     * onConfigurationChanged events for updating tutorial text.
     */
    public void onConfigurationChanged() {
        updateThemeColors();

        if (mCurrentState != STATE_ACTIVE) {
            return;
        }
        showBackgroundPanelLayer();
    }

    private void updateThemeColors() {
        final Context themedContext = new ContextThemeWrapper(mContext,
                com.android.internal.R.style.Theme_DeviceDefault_DayNight);
        final int themeColor = themedContext.getColor(
                R.color.one_handed_tutorial_background_color);
        mThemeColor = new float[]{
                adjustColor(Color.red(themeColor)),
                adjustColor(Color.green(themeColor)),
                adjustColor(Color.blue(themeColor))};
    }

    private float adjustColor(int origColor) {
        return Math.max(origColor - THEME_COLOR_OFFSET, 0) / 255.0f;
    }

    @Override
    public void onStateChanged(int newState) {
        mCurrentState = newState;
    }

    void dump(@NonNull PrintWriter pw) {
        final String innerPrefix = "  ";
        pw.println(TAG);
        pw.print(innerPrefix + "mBackgroundSurface=");
        pw.println(mBackgroundSurface);
        pw.print(innerPrefix + "mBkgBounds=");
        pw.println(mBkgBounds);
        pw.print(innerPrefix + "mThemeColor=");
        pw.println(mThemeColor);
        pw.print(innerPrefix + "mTranslationFraction=");
        pw.println(mTranslationFraction);
    }
}
+6 −28
Original line number Diff line number Diff line
@@ -99,7 +99,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,

    private OneHandedEventCallback mEventCallback;
    private OneHandedDisplayAreaOrganizer mDisplayAreaOrganizer;
    private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer;
    private OneHandedUiEventLogger mOneHandedUiEventLogger;

    private final DisplayController.OnDisplaysChangedListener mDisplaysChangedListener =
@@ -163,7 +162,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
                public void onStopFinished(Rect bounds) {
                    mState.setState(STATE_NONE);
                    notifyShortcutStateChanged(STATE_NONE);
                    mBackgroundPanelOrganizer.onStopFinished();
                }
            };

@@ -207,26 +205,21 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
                new OneHandedAnimationController(context);
        OneHandedTouchHandler touchHandler = new OneHandedTouchHandler(timeoutHandler,
                mainExecutor);
        OneHandedBackgroundPanelOrganizer oneHandedBackgroundPanelOrganizer =
                new OneHandedBackgroundPanelOrganizer(context, displayLayout, settingsUtil,
                        mainExecutor);
        OneHandedDisplayAreaOrganizer organizer = new OneHandedDisplayAreaOrganizer(
                context, displayLayout, settingsUtil, animationController, tutorialHandler,
                oneHandedBackgroundPanelOrganizer, jankMonitor, mainExecutor);
                jankMonitor, mainExecutor);
        OneHandedUiEventLogger oneHandedUiEventsLogger = new OneHandedUiEventLogger(uiEventLogger);
        IOverlayManager overlayManager = IOverlayManager.Stub.asInterface(
                ServiceManager.getService(Context.OVERLAY_SERVICE));
        return new OneHandedController(context, displayController,
                oneHandedBackgroundPanelOrganizer, organizer, touchHandler, tutorialHandler,
                settingsUtil, accessibilityUtil, timeoutHandler, oneHandedState, jankMonitor,
                oneHandedUiEventsLogger, overlayManager, taskStackListener, mainExecutor,
                mainHandler);
        return new OneHandedController(context, displayController, organizer, touchHandler,
                tutorialHandler, settingsUtil, accessibilityUtil, timeoutHandler, oneHandedState,
                jankMonitor, oneHandedUiEventsLogger, overlayManager, taskStackListener,
                mainExecutor, mainHandler);
    }

    @VisibleForTesting
    OneHandedController(Context context,
            DisplayController displayController,
            OneHandedBackgroundPanelOrganizer backgroundPanelOrganizer,
            OneHandedDisplayAreaOrganizer displayAreaOrganizer,
            OneHandedTouchHandler touchHandler,
            OneHandedTutorialHandler tutorialHandler,
@@ -243,7 +236,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
        mContext = context;
        mOneHandedSettingsUtil = settingsUtil;
        mOneHandedAccessibilityUtil = oneHandedAccessibilityUtil;
        mBackgroundPanelOrganizer = backgroundPanelOrganizer;
        mDisplayAreaOrganizer = displayAreaOrganizer;
        mDisplayController = displayController;
        mTouchHandler = touchHandler;
@@ -286,7 +278,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
        mAccessibilityManager.addAccessibilityStateChangeListener(
                mAccessibilityStateChangeListener);

        mState.addSListeners(mBackgroundPanelOrganizer);
        mState.addSListeners(mTutorialHandler);
    }

@@ -368,7 +359,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
                mDisplayAreaOrganizer.getDisplayLayout().height() * mOffSetFraction);
        mOneHandedAccessibilityUtil.announcementForScreenReader(
                mOneHandedAccessibilityUtil.getOneHandedStartDescription());
        mBackgroundPanelOrganizer.onStart();
        mDisplayAreaOrganizer.scheduleOffset(0, yOffSet);
        mTimeoutHandler.resetTimer();
        mOneHandedUiEventLogger.writeEvent(
@@ -461,7 +451,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
        }
        mDisplayAreaOrganizer.setDisplayLayout(newDisplayLayout);
        mTutorialHandler.onDisplayChanged(newDisplayLayout);
        mBackgroundPanelOrganizer.onDisplayChanged(newDisplayLayout);
    }

    private ContentObserver getObserver(Runnable onChangeRunnable) {
@@ -585,7 +574,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,

        if (!mIsOneHandedEnabled) {
            mDisplayAreaOrganizer.unregisterOrganizer();
            mBackgroundPanelOrganizer.unregisterOrganizer();
            // Do NOT register + unRegister DA in the same call
            return;
        }
@@ -594,11 +582,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
            mDisplayAreaOrganizer.registerOrganizer(
                    OneHandedDisplayAreaOrganizer.FEATURE_ONE_HANDED);
        }

        if (!mBackgroundPanelOrganizer.isRegistered()) {
            mBackgroundPanelOrganizer.registerOrganizer(
                    OneHandedBackgroundPanelOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL);
        }
    }

    @VisibleForTesting
@@ -613,13 +596,12 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
    }

    private void onConfigChanged(Configuration newConfig) {
        if (mTutorialHandler == null || mBackgroundPanelOrganizer == null) {
        if (mTutorialHandler == null) {
            return;
        }
        if (!mIsOneHandedEnabled || newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
            return;
        }
        mBackgroundPanelOrganizer.onConfigurationChanged();
        mTutorialHandler.onConfigurationChanged();
    }

@@ -650,10 +632,6 @@ public class OneHandedController implements RemoteCallable<OneHandedController>,
        pw.print(innerPrefix + "mIsSwipeToNotificationEnabled=");
        pw.println(mIsSwipeToNotificationEnabled);

        if (mBackgroundPanelOrganizer != null) {
            mBackgroundPanelOrganizer.dump(pw);
        }

        if (mDisplayAreaOrganizer != null) {
            mDisplayAreaOrganizer.dump(pw);
        }
+0 −4
Original line number Diff line number Diff line
@@ -80,7 +80,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
            mSurfaceControlTransactionFactory;
    private OneHandedTutorialHandler mTutorialHandler;
    private List<OneHandedTransitionCallback> mTransitionCallbacks = new ArrayList<>();
    private OneHandedBackgroundPanelOrganizer mBackgroundPanelOrganizer;

    @VisibleForTesting
    OneHandedAnimationCallback mOneHandedAnimationCallback =
@@ -135,7 +134,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
            OneHandedSettingsUtil oneHandedSettingsUtil,
            OneHandedAnimationController animationController,
            OneHandedTutorialHandler tutorialHandler,
            OneHandedBackgroundPanelOrganizer oneHandedBackgroundGradientOrganizer,
            InteractionJankMonitor jankMonitor,
            ShellExecutor mainExecutor) {
        super(mainExecutor);
@@ -150,7 +148,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
                SystemProperties.getInt(ONE_HANDED_MODE_TRANSLATE_ANIMATION_DURATION,
                        animationDurationConfig);
        mSurfaceControlTransactionFactory = SurfaceControl.Transaction::new;
        mBackgroundPanelOrganizer = oneHandedBackgroundGradientOrganizer;
        mTutorialHandler = tutorialHandler;
    }

@@ -258,7 +255,6 @@ public class OneHandedDisplayAreaOrganizer extends DisplayAreaOrganizer {
            animator.setTransitionDirection(direction)
                    .addOneHandedAnimationCallback(mOneHandedAnimationCallback)
                    .addOneHandedAnimationCallback(mTutorialHandler)
                    .addOneHandedAnimationCallback(mBackgroundPanelOrganizer)
                    .setDuration(durationMs)
                    .start();
        }
+0 −131
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.wm.shell.onehanded;

import static android.view.Display.DEFAULT_DISPLAY;
import static android.window.DisplayAreaOrganizer.FEATURE_ONE_HANDED_BACKGROUND_PANEL;

import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE;
import static com.android.wm.shell.onehanded.OneHandedState.STATE_NONE;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.Display;
import android.view.SurfaceControl;
import android.window.DisplayAreaInfo;
import android.window.IWindowContainerToken;
import android.window.WindowContainerToken;

import androidx.test.filters.SmallTest;

import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayLayout;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

@SmallTest
@RunWith(AndroidTestingRunner.class)
@TestableLooper.RunWithLooper
public class OneHandedBackgroundPanelOrganizerTest extends OneHandedTestCase {
    private DisplayAreaInfo mDisplayAreaInfo;
    private Display mDisplay;
    private DisplayLayout mDisplayLayout;
    private OneHandedBackgroundPanelOrganizer mSpiedBackgroundPanelOrganizer;
    private WindowContainerToken mToken;
    private SurfaceControl mLeash;

    @Mock
    IWindowContainerToken mMockRealToken;
    @Mock
    DisplayController mMockDisplayController;
    @Mock
    OneHandedSettingsUtil mMockSettingsUtil;

    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mToken = new WindowContainerToken(mMockRealToken);
        mLeash = new SurfaceControl();
        mDisplay = mContext.getDisplay();
        mDisplayLayout = new DisplayLayout(mContext, mDisplay);
        when(mMockDisplayController.getDisplay(anyInt())).thenReturn(mDisplay);
        mDisplayAreaInfo = new DisplayAreaInfo(mToken, DEFAULT_DISPLAY,
                FEATURE_ONE_HANDED_BACKGROUND_PANEL);

        mSpiedBackgroundPanelOrganizer = spy(
                new OneHandedBackgroundPanelOrganizer(mContext, mDisplayLayout, mMockSettingsUtil,
                        Runnable::run));
        mSpiedBackgroundPanelOrganizer.onDisplayChanged(mDisplayLayout);
    }

    @Test
    public void testOnDisplayAreaAppeared() {
        mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);

        assertThat(mSpiedBackgroundPanelOrganizer.isRegistered()).isTrue();
        verify(mSpiedBackgroundPanelOrganizer, never()).showBackgroundPanelLayer();
    }

    @Test
    public void testShowBackgroundLayer() {
        mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, null);
        mSpiedBackgroundPanelOrganizer.onStart();

        verify(mSpiedBackgroundPanelOrganizer).showBackgroundPanelLayer();
    }

    @Test
    public void testRemoveBackgroundLayer() {
        mSpiedBackgroundPanelOrganizer.onDisplayAreaAppeared(mDisplayAreaInfo, mLeash);

        assertThat(mSpiedBackgroundPanelOrganizer.isRegistered()).isNotNull();

        reset(mSpiedBackgroundPanelOrganizer);
        mSpiedBackgroundPanelOrganizer.removeBackgroundPanelLayer();

        assertThat(mSpiedBackgroundPanelOrganizer.mBackgroundSurface).isNull();
    }

    @Test
    public void testStateNone_onConfigurationChanged() {
        mSpiedBackgroundPanelOrganizer.onStateChanged(STATE_NONE);
        mSpiedBackgroundPanelOrganizer.onConfigurationChanged();

        verify(mSpiedBackgroundPanelOrganizer, never()).showBackgroundPanelLayer();
    }

    @Test
    public void testStateActivate_onConfigurationChanged() {
        mSpiedBackgroundPanelOrganizer.onStateChanged(STATE_ACTIVE);
        mSpiedBackgroundPanelOrganizer.onConfigurationChanged();

        verify(mSpiedBackgroundPanelOrganizer).showBackgroundPanelLayer();
    }
}
Loading