mirror of
https://gitee.com/houstudio/Cdroid.git
synced 2024-11-30 03:08:12 +08:00
LookupTableInterpolator's crash(caused by uninit),modify popupwindow
This commit is contained in:
parent
50127d9673
commit
46f118dfdd
7
src/3rdparty/cairo-1.16.0/CMakeLists.txt
vendored
7
src/3rdparty/cairo-1.16.0/CMakeLists.txt
vendored
@ -6,7 +6,7 @@ find_package(ZLIB REQUIRED)
|
||||
find_package(Freetype)
|
||||
find_package(Threads)
|
||||
find_package(Fontconfig)
|
||||
|
||||
find_package(OpenGL)
|
||||
|
||||
include(Configure_config.cmake)
|
||||
include(Configure_features.cmake)
|
||||
@ -35,5 +35,10 @@ if(FREETYPE_FOUND)
|
||||
list(APPEND CAIRO_LIBS ${FREETYPE_LIBRARIES} ${BZIP2_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(OPENGL_FOUND)
|
||||
list(APPEND CAIRO_LIBS ${OPENGL_LIBRARIES})
|
||||
include_directories(OPENGL_INCLUDE_DIR)
|
||||
endif()
|
||||
|
||||
include_directories(src)
|
||||
add_subdirectory(src)
|
||||
|
4
src/3rdparty/cairo-1.16.0/Configure_config.cmake
vendored
Normal file → Executable file
4
src/3rdparty/cairo-1.16.0/Configure_config.cmake
vendored
Normal file → Executable file
@ -28,11 +28,11 @@ endif()
|
||||
|
||||
if(THREADS_FOUND)
|
||||
set(CAIRO_HAR_REAL_PTHREAD 1)
|
||||
set(CAIRO_HAS_PTHREAD 1)
|
||||
set(CAIRO_HAS_PTHREAD 1)
|
||||
endif()
|
||||
|
||||
if(VALGRIND_FOUND)
|
||||
set(HAVE_VALGRIND 1)
|
||||
set(HAVE_VALGRIND 1)
|
||||
endif()
|
||||
|
||||
check_include_file( "byteswap.h" HAVE_BYTESWAP_H )
|
||||
|
6
src/3rdparty/cairo-1.16.0/Configure_features.cmake
vendored
Normal file → Executable file
6
src/3rdparty/cairo-1.16.0/Configure_features.cmake
vendored
Normal file → Executable file
@ -92,16 +92,14 @@ if (MINIMAL_SIZE_OPTIMIZED )
|
||||
set(CAIRO_HAS_VG_SURFACE 0)
|
||||
set(CAIRO_HAS_XML_SURFACE 0)
|
||||
set(CAIRO_HAS_EGL_FUNCTIONS 0)
|
||||
set(CAIRO_HAS_GLX_FUNCTIONS 0)
|
||||
set(CAIRO_HAS_WGL_FUNCTIONS 0)
|
||||
set(CAIRO_HAS_TEST_SURFACES 0)
|
||||
set(CAIRO_HAS_TEE_SURFACE 0)
|
||||
|
||||
set(CAIRO_HAS_PTHREAD 0)
|
||||
set(CAIRO_HAS_TRACE 0)
|
||||
set(CAIRO_HAS_SYMBOL_LOOKUP 0)
|
||||
set(CAIRO_HAS_PS_SURFACE 0)
|
||||
set(CAIRO_HAS_PDF_SURFACE 0)
|
||||
set(CAIRO_HAS_PS_SURFACE 0)
|
||||
set(CAIRO_HAS_PDF_SURFACE 0)
|
||||
set(CAIRO_HAS_QT_SURFACE 0)
|
||||
endif( MINIMAL_SIZE_OPTIMIZED )
|
||||
|
||||
|
@ -422,7 +422,7 @@ void Animation::getInvalidateRegion(int left, int top, int width, int height,
|
||||
Rect previousRegion = mPreviousRegion;
|
||||
|
||||
invalidate.set(left, top, width, height);
|
||||
transformation.getMatrix().transform_rectangle((const RectangleInt&)invalidate,(RectangleInt&)invalidate);
|
||||
transformation.getMatrix().transform_rectangle((RectangleInt&)invalidate);
|
||||
// Enlarge the invalidate region to account for rounding errors
|
||||
invalidate.inflate(-1,-1);//inset(-1.0f, -1.0f);
|
||||
tempRegion=invalidate;//.set(invalidate);
|
||||
|
@ -624,6 +624,7 @@ AlertController::AlertParams::AlertParams(Context*context){
|
||||
mCursor = nullptr;
|
||||
mCustomTitleView= nullptr;
|
||||
mInflater= LayoutInflater::from(mContext);
|
||||
LOGD("%p",this);
|
||||
}
|
||||
|
||||
void AlertController::AlertParams::apply(AlertController* dialog){
|
||||
|
@ -6,6 +6,7 @@ AlertDialog::AlertDialog(Context*ctx):AlertDialog(ctx,false,nullptr){
|
||||
|
||||
AlertDialog::AlertDialog(Context*ctx,const std::string&resid):Dialog(ctx,resid){
|
||||
mAlert = AlertController::create(getContext(), this, getWindow());
|
||||
P = nullptr;
|
||||
}
|
||||
|
||||
AlertDialog::AlertDialog(Context*ctx,bool cancelable,DialogInterface::OnCancelListener listener)
|
||||
@ -14,6 +15,11 @@ AlertDialog::AlertDialog(Context*ctx,bool cancelable,DialogInterface::OnCancelLi
|
||||
setOnCancelListener(listener);
|
||||
}
|
||||
|
||||
AlertDialog::~AlertDialog(){
|
||||
delete mAlert;
|
||||
delete P;
|
||||
}
|
||||
|
||||
void AlertDialog::setTitle(const std::string& title){
|
||||
Dialog::setTitle(title);
|
||||
mAlert->setTitle(title);
|
||||
@ -40,6 +46,14 @@ void AlertDialog::setButton(int whichButton,const std::string&text, OnClickListe
|
||||
mAlert->setButton(whichButton, text, listener);
|
||||
}
|
||||
|
||||
Button* AlertDialog::getButton(int whichButton) {
|
||||
return mAlert->getButton(whichButton);
|
||||
}
|
||||
|
||||
ListView* AlertDialog::getListView() {
|
||||
return mAlert->getListView();
|
||||
}
|
||||
|
||||
void AlertDialog::setIcon(const std::string&iconId){
|
||||
mAlert->setIcon(iconId);
|
||||
}
|
||||
@ -250,6 +264,7 @@ AlertDialog* AlertDialog::Builder::create(){
|
||||
if (P->mOnKeyListener != nullptr) {
|
||||
dialog->setOnKeyListener(P->mOnKeyListener);
|
||||
}
|
||||
dialog->P=P;
|
||||
return dialog;
|
||||
}
|
||||
|
||||
|
@ -49,14 +49,17 @@ public:
|
||||
AlertDialog* show();
|
||||
};
|
||||
protected:
|
||||
friend Builder;
|
||||
class AlertController* mAlert;
|
||||
AlertController::AlertParams*P;
|
||||
protected:
|
||||
AlertDialog(Context*ctx);
|
||||
AlertDialog(Context*ctx,const std::string&resid);
|
||||
AlertDialog(Context*ctx,bool cancelable,OnCancelListener listener);
|
||||
~AlertDialog()override;
|
||||
void onCreate()override;
|
||||
public:
|
||||
Button*getButton(int whichButton);
|
||||
Button* getButton(int whichButton);
|
||||
ListView* getListView();
|
||||
void setTitle(const std::string& title);
|
||||
void setCustomTitle(View*customTitleView);
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <app/dialog.h>
|
||||
#include <core/windowmanager.h>
|
||||
namespace cdroid{
|
||||
|
||||
Dialog::Dialog(Context*context){
|
||||
@ -15,6 +16,9 @@ Dialog::Dialog(Context* context,const std::string&resId):Dialog(context){
|
||||
}
|
||||
|
||||
Dialog::~Dialog(){
|
||||
if(mWindow){
|
||||
WindowManager::getInstance().removeWindow(mWindow);
|
||||
}
|
||||
}
|
||||
|
||||
Context*Dialog::getContext()const{
|
||||
@ -65,6 +69,7 @@ void Dialog::dismissDialog(){
|
||||
mShowing = false;
|
||||
if(mOnDismissListener)
|
||||
mOnDismissListener(*this);
|
||||
mWindow->setVisibility(View::INVISIBLE);
|
||||
}
|
||||
|
||||
void Dialog::dispatchOnCreate(void*buddle){
|
||||
|
@ -103,12 +103,12 @@ Matrix operator*(const Matrix& a, const Matrix& b)
|
||||
return m;
|
||||
}
|
||||
|
||||
void Matrix::transform_rectangle(const RectangleInt& from,Rectangle&to)const{
|
||||
void Matrix::transform_rectangle(Rectangle& io)const{
|
||||
double pt[8];
|
||||
pt[0] = pt[6] = from.x ;
|
||||
pt[1] = pt[3] = from.y ;
|
||||
pt[2] = pt[4] = from.x + from.width;
|
||||
pt[5] = pt[7] = from.x + from.height;
|
||||
pt[0] = pt[6] = io.x ;
|
||||
pt[1] = pt[3] = io.y ;
|
||||
pt[2] = pt[4] = io.x + io.width;
|
||||
pt[5] = pt[7] = io.x + io.height;
|
||||
double x1=INT_MAX,y1=INT_MAX;
|
||||
double x2=INT_MIN,y2=INT_MIN;
|
||||
for(int i=0;i<8;i+=2){
|
||||
@ -118,19 +118,19 @@ void Matrix::transform_rectangle(const RectangleInt& from,Rectangle&to)const{
|
||||
x2 = std::max(x2,pt[i]);
|
||||
y2 = std::max(y2,pt[i+1]);
|
||||
}
|
||||
to.x = (int)std::floor(x1);
|
||||
to.y = (int)std::floor(y1);
|
||||
to.width = (int)std::ceil(x2) - to.x;
|
||||
to.height= (int)std::ceil(y2) - to.y;
|
||||
io.x = x1;//std::floor(x1);
|
||||
io.y = y1;//std::floor(y1);
|
||||
io.width = x2 - x1;//std::ceil(x2) - to.x;
|
||||
io.height= y2 - y1;//std::ceil(y2) - to.y;
|
||||
}
|
||||
|
||||
void Matrix::transform_rectangle(const RectangleInt& from,RectangleInt&to)const{
|
||||
Rectangle tof;
|
||||
transform_rectangle(from,tof);
|
||||
to.x= std::floor(tof.x);
|
||||
to.y = (int)std::floor(tof.y);
|
||||
to.width = (int)std::ceil(tof.width);
|
||||
to.height= (int)std::ceil(tof.height);
|
||||
void Matrix::transform_rectangle(RectangleInt& io)const{
|
||||
Rectangle tmp={io.x,io.y,io.width,io.height};
|
||||
transform_rectangle(tmp);
|
||||
io.x = (int)std::floor(tmp.x);
|
||||
io.y = (int)std::floor(tmp.y);
|
||||
io.width = (int)std::ceil(tmp.width);
|
||||
io.height= (int)std::ceil(tmp.height);
|
||||
}
|
||||
|
||||
} // namespace Cairo
|
||||
|
@ -161,8 +161,8 @@ public:
|
||||
void transform_point(double& x, double& y) const;
|
||||
|
||||
/*added by zhhou*/
|
||||
void transform_rectangle(const RectangleInt& from,Rectangle&to)const;
|
||||
void transform_rectangle(const RectangleInt& from,RectangleInt&to)const;
|
||||
void transform_rectangle(Rectangle& inout)const;
|
||||
void transform_rectangle(RectangleInt& inout)const;
|
||||
};
|
||||
|
||||
/** Returns a Matrix initialized to the identity matrix
|
||||
|
@ -310,6 +310,7 @@ public:
|
||||
EDGE_RIGHT = 0x0008
|
||||
};
|
||||
enum{
|
||||
INVALID_POINTER_ID = -1,
|
||||
AXIS_X = 0,
|
||||
AXIS_Y = 1,
|
||||
AXIS_PRESSURE = 2,
|
||||
|
@ -29,7 +29,7 @@ WindowManager* WindowManager::mInst = nullptr;
|
||||
|
||||
WindowManager::WindowManager(){
|
||||
GraphDevice::getInstance();
|
||||
activeWindow=nullptr;
|
||||
mActiveWindow = nullptr;
|
||||
}
|
||||
|
||||
WindowManager&WindowManager::getInstance(){
|
||||
@ -40,34 +40,34 @@ WindowManager&WindowManager::getInstance(){
|
||||
};
|
||||
|
||||
WindowManager::~WindowManager() {
|
||||
for(Window*w:windows){
|
||||
View::AttachInfo*info=w->mAttachInfo;
|
||||
for(Window*w:mWindows){
|
||||
View::AttachInfo*info = w->mAttachInfo;
|
||||
w->dispatchDetachedFromWindow();
|
||||
delete info;
|
||||
delete w;
|
||||
};
|
||||
windows.clear();
|
||||
mWindows.clear();
|
||||
LOGD("%p Destroied",this);
|
||||
}
|
||||
|
||||
void WindowManager::addWindow(Window*win){
|
||||
windows.push_back(win);
|
||||
std::sort(windows.begin(),windows.end(),[](Window*w1,Window*w2){
|
||||
mWindows.push_back(win);
|
||||
std::sort(mWindows.begin(),mWindows.end(),[](Window*w1,Window*w2){
|
||||
return (w2->window_type-w1->window_type)>0;
|
||||
});
|
||||
|
||||
for(int idx=0,type_idx=0;idx<windows.size();idx++){
|
||||
Window*w=windows.at(idx);
|
||||
if(w->window_type!=windows[type_idx]->window_type)
|
||||
for(int idx=0,type_idx=0;idx<mWindows.size();idx++){
|
||||
Window*w = mWindows.at(idx);
|
||||
if(w->window_type != mWindows[type_idx]->window_type)
|
||||
type_idx=idx;
|
||||
w->mLayer=w->window_type*10000+(idx-type_idx)*5;
|
||||
LOGV("%p window %p[%s] type=%d layer=%d",win,w,w->getText().c_str(),w->window_type,w->mLayer);
|
||||
}
|
||||
if(activeWindow)activeWindow->post(std::bind(&Window::onDeactive,activeWindow));
|
||||
if(mActiveWindow)mActiveWindow->post(std::bind(&Window::onDeactive,mActiveWindow));
|
||||
|
||||
View::AttachInfo*info=new View::AttachInfo();
|
||||
View::AttachInfo*info = new View::AttachInfo();
|
||||
info->mContentInsets.set(5,5,5,5);
|
||||
info->mRootView=win;
|
||||
info->mRootView = win;
|
||||
win->dispatchAttachedToWindow(info,win->getVisibility());
|
||||
#if USE_UIEVENTHANDLER
|
||||
Looper::getDefault()->addHandler(win->mUIEventHandler);
|
||||
@ -75,20 +75,20 @@ void WindowManager::addWindow(Window*win){
|
||||
Looper::getDefault()->addEventHandler(win->mUIEventHandler);
|
||||
#endif
|
||||
win->post(std::bind(&Window::onActive,win));
|
||||
activeWindow=win;
|
||||
LOGV("win=%p Handler=%p windows.size=%d",win,win->mUIEventHandler,windows.size());
|
||||
mActiveWindow = win;
|
||||
LOGV("win=%p Handler=%p windows.size=%d",win,win->mUIEventHandler,mWindows.size());
|
||||
}
|
||||
|
||||
void WindowManager::removeWindow(Window*w){
|
||||
if(w==activeWindow)activeWindow=nullptr;
|
||||
if(w == mActiveWindow)mActiveWindow = nullptr;
|
||||
if(w->hasFlag(View::FOCUSABLE))
|
||||
w->onDeactive();
|
||||
auto itw=std::find(windows.begin(),windows.end(),w);
|
||||
const Rect wrect=w->getBound();
|
||||
windows.erase(itw);
|
||||
for(auto itr=windows.begin();itr!=windows.end();itr++){
|
||||
Window*w1=(*itr);
|
||||
RECT rc=w1->getBound();
|
||||
auto itw = std::find(mWindows.begin(),mWindows.end(),w);
|
||||
const Rect wrect = w->getBound();
|
||||
mWindows.erase(itw);
|
||||
for(auto itr=mWindows.begin();itr!=mWindows.end();itr++){
|
||||
Window*w1 = (*itr);
|
||||
RECT rc = w1->getBound();
|
||||
rc.intersect(wrect);
|
||||
rc.offset(-w1->getX(),-w1->getY());
|
||||
w1->invalidate(&rc);
|
||||
@ -98,46 +98,49 @@ void WindowManager::removeWindow(Window*w){
|
||||
#else
|
||||
Looper::getDefault()->removeEventHandler(w->mUIEventHandler);
|
||||
#endif
|
||||
View::AttachInfo*info=w->mAttachInfo;
|
||||
View::AttachInfo*info = w->mAttachInfo;
|
||||
w->dispatchDetachedFromWindow();
|
||||
delete info;
|
||||
delete w;
|
||||
for(auto it=windows.rbegin();it!=windows.rend();it++){
|
||||
for(auto it=mWindows.rbegin();it!=mWindows.rend();it++){
|
||||
if((*it)->hasFlag(View::FOCUSABLE)&&(*it)->getVisibility()==View::VISIBLE){
|
||||
(*it)->onActive();
|
||||
activeWindow=(*it);
|
||||
mActiveWindow=(*it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
GraphDevice::getInstance().invalidate(wrect);
|
||||
GraphDevice::getInstance().flip();
|
||||
LOGV("w=%p windows.size=%d",w,windows.size());
|
||||
LOGV("w=%p windows.size=%d",w,mWindows.size());
|
||||
}
|
||||
|
||||
void WindowManager::moveWindow(Window*w,int x,int y){
|
||||
if( (w->isAttachedToWindow()==false)||(w->getVisibility()!=View::VISIBLE))
|
||||
return;
|
||||
Rect rcw=w->getBound();
|
||||
GraphDevice::getInstance().invalidate(rcw);
|
||||
rcw.left=x;rcw.top=y;
|
||||
GraphDevice::getInstance().invalidate(rcw);
|
||||
GraphDevice::getInstance().flip();
|
||||
Rect rcw = w->getBound();
|
||||
Rect rcw2 =rcw;
|
||||
rcw2.left = x;
|
||||
rcw2.top = y;
|
||||
w->setFrame(x,y,rcw.width,rcw.height);
|
||||
if( w->isAttachedToWindow() && (w->getVisibility()==View::VISIBLE)){
|
||||
GraphDevice::getInstance().invalidate(rcw);
|
||||
GraphDevice::getInstance().invalidate(rcw2);
|
||||
GraphDevice::getInstance().flip();
|
||||
}
|
||||
}
|
||||
|
||||
int WindowManager::enumWindows(WNDENUMPROC cbk){
|
||||
int rc=0;
|
||||
for(auto& w:windows)
|
||||
int rc = 0;
|
||||
for(auto& w:mWindows)
|
||||
rc+=cbk(w);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int WindowManager::getWindows(std::vector<Window*>&wins){
|
||||
wins=windows;
|
||||
return windows.size();
|
||||
wins = mWindows;
|
||||
return mWindows.size();
|
||||
}
|
||||
|
||||
int WindowManager::getVisibleWindows(std::vector<Window*>&wins){
|
||||
for(auto& w:windows){
|
||||
for(auto& w:mWindows){
|
||||
if(w->getVisibility()==View::VISIBLE)
|
||||
wins.push_back(w);
|
||||
}
|
||||
@ -155,11 +158,11 @@ void WindowManager::processEvent(InputEvent&e){
|
||||
|
||||
void WindowManager::onMotion(MotionEvent&event) {
|
||||
// Notify the focused child
|
||||
const int x=event.getX();
|
||||
const int y=event.getY();
|
||||
for (auto itr=windows.rbegin();itr!=windows.rend();itr++) {
|
||||
auto w=(*itr);
|
||||
if ((w->getVisibility()==View::VISIBLE)&&w->getBound().contains(x,y)) {
|
||||
const int x = event.getX();
|
||||
const int y = event.getY();
|
||||
for (auto itr = mWindows.rbegin();itr != mWindows.rend();itr++) {
|
||||
auto w = (*itr);
|
||||
if ((w->getVisibility()==View::VISIBLE) && w->getBound().contains(x,y)) {
|
||||
event.offsetLocation(-w->getX(),-w->getY());
|
||||
w->dispatchTouchEvent(event);
|
||||
event.offsetLocation(w->getX(),w->getY());
|
||||
@ -170,10 +173,10 @@ void WindowManager::onMotion(MotionEvent&event) {
|
||||
|
||||
void WindowManager::onKeyEvent(KeyEvent&event) {
|
||||
// Notify the focused child
|
||||
for (auto itr=windows.rbegin() ;itr!= windows.rend();itr++) {
|
||||
Window*win=(*itr);
|
||||
if ( win->hasFlag(View::FOCUSABLE)&&(win->getVisibility()==View::VISIBLE) ) {
|
||||
int keyCode=event.getKeyCode();
|
||||
for (auto itr = mWindows.rbegin() ;itr != mWindows.rend();itr++) {
|
||||
Window*win = (*itr);
|
||||
if ( win->hasFlag(View::FOCUSABLE) && (win->getVisibility()==View::VISIBLE) ) {
|
||||
int keyCode = event.getKeyCode();
|
||||
LOGV("Window:%p Key:%s[%x] action=%d",win,event.getLabel(keyCode),keyCode,event.getAction());
|
||||
win->processKeyEvent(event);
|
||||
//dispatchKeyEvent(event);
|
||||
@ -183,11 +186,11 @@ void WindowManager::onKeyEvent(KeyEvent&event) {
|
||||
}
|
||||
|
||||
void WindowManager::clip(Window*win){
|
||||
RECT rcw=win->getBound();
|
||||
for (auto wind=windows.rbegin() ;wind!= windows.rend();wind++){
|
||||
RECT rcw = win->getBound();
|
||||
for (auto wind = mWindows.rbegin() ;wind != mWindows.rend();wind++){
|
||||
if( (*wind)==win )break;
|
||||
if( (*wind)->getVisibility()!=View::VISIBLE)continue;
|
||||
Rect rc=rcw;
|
||||
Rect rc = rcw;
|
||||
rc.intersect((*wind)->getBound());
|
||||
if(rc.empty())continue;
|
||||
rc.offset(-win->getX(),-win->getY());
|
||||
|
@ -28,6 +28,14 @@ namespace cdroid {
|
||||
class WindowManager {
|
||||
public:
|
||||
DECLARE_UIEVENT(bool,WNDENUMPROC,Window*);
|
||||
class LayoutParams:public ViewGroup::LayoutParams{
|
||||
public:
|
||||
int x,y;
|
||||
int width,height;
|
||||
int gravity;
|
||||
int flags;
|
||||
};
|
||||
public:
|
||||
static WindowManager& getInstance();
|
||||
void addWindow(Window*w);
|
||||
void removeWindow(Window*w);
|
||||
@ -45,8 +53,8 @@ private:
|
||||
friend class GraphDevice;
|
||||
WindowManager();
|
||||
virtual ~WindowManager();
|
||||
Window*activeWindow;/*activeWindow*/
|
||||
std::vector< Window* > windows;
|
||||
Window*mActiveWindow;/*activeWindow*/
|
||||
std::vector< Window* > mWindows;
|
||||
static WindowManager* mInst;
|
||||
DISALLOW_COPY_AND_ASSIGN(WindowManager);
|
||||
};
|
20
src/gui/view/layoutparams.cc
Normal file → Executable file
20
src/gui/view/layoutparams.cc
Normal file → Executable file
@ -4,22 +4,22 @@
|
||||
namespace cdroid{
|
||||
|
||||
LayoutParams::LayoutParams(){
|
||||
layoutAnimationParameters =nullptr;
|
||||
}
|
||||
|
||||
LayoutParams::LayoutParams(Context* c,const AttributeSet& attrs){
|
||||
LayoutParams::LayoutParams(Context* c,const AttributeSet& attrs):LayoutParams(){
|
||||
width =attrs.getLayoutDimension("layout_width" ,WRAP_CONTENT);
|
||||
height=attrs.getLayoutDimension("layout_height",WRAP_CONTENT);
|
||||
layoutAnimationParameters=nullptr;
|
||||
}
|
||||
|
||||
LayoutParams::LayoutParams(int w, int h):width(w),height(h){
|
||||
layoutAnimationParameters=nullptr;
|
||||
LayoutParams::LayoutParams(int w, int h):LayoutParams(){
|
||||
width = w;
|
||||
height= h;
|
||||
}
|
||||
|
||||
LayoutParams::LayoutParams(const LayoutParams& source){
|
||||
width=source.width;
|
||||
height=source.height;
|
||||
layoutAnimationParameters=nullptr;
|
||||
LayoutParams::LayoutParams(const LayoutParams& source):LayoutParams(){
|
||||
width = source.width;
|
||||
height= source.height;
|
||||
}
|
||||
|
||||
LayoutParams::~LayoutParams(){
|
||||
@ -27,8 +27,8 @@ LayoutParams::~LayoutParams(){
|
||||
}
|
||||
|
||||
void LayoutParams::setBaseAttributes(const AttributeSet& a, int widthAttr, int heightAttr){
|
||||
//width = a.getLayoutDimension(widthAttr, "layout_width");
|
||||
//height= a.getLayoutDimension(heightAttr, "layout_height");
|
||||
width = a.getLayoutDimension("layout_width",WRAP_CONTENT);
|
||||
height= a.getLayoutDimension("layout_height",WRAP_CONTENT);
|
||||
}
|
||||
|
||||
void LayoutParams::resolveLayoutDirection(int layoutDirection){
|
||||
|
2
src/gui/view/layoutparams.h
Normal file → Executable file
2
src/gui/view/layoutparams.h
Normal file → Executable file
@ -65,7 +65,7 @@ public:
|
||||
void setMarginEnd(int end);
|
||||
int getMarginEnd();
|
||||
bool isMarginRelative()const;
|
||||
void setLayoutDirection(int layoutDirection);//override;
|
||||
void setLayoutDirection(int layoutDirection);
|
||||
int getLayoutDirection()const;
|
||||
void resolveLayoutDirection(int layoutDirection)override;
|
||||
bool isLayoutRtl()const;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include <view/swipehelper.h>
|
||||
#include <core/systemclock.h>
|
||||
#include <private/windowmanager.h>
|
||||
#include <core/windowmanager.h>
|
||||
#include <cdlog.h>
|
||||
namespace cdroid{
|
||||
|
||||
|
@ -67,6 +67,7 @@ class ListenerInfo{
|
||||
public:
|
||||
View::OnFocusChangeListener mOnFocusChangeListener;
|
||||
std::vector<View::OnLayoutChangeListener> mOnLayoutChangeListeners;
|
||||
std::vector<View::OnAttachStateChangeListener> mOnAttachStateChangeListeners;
|
||||
View::OnScrollChangeListener mOnScrollChangeListener;
|
||||
View::OnClickListener mOnClickListener;
|
||||
View::OnLongClickListener mOnLongClickListener;
|
||||
@ -1214,7 +1215,33 @@ void View::transformFromViewToWindowSpace(int*inOutLocation){
|
||||
}
|
||||
|
||||
void View::mapRectFromViewToScreenCoords(Rect& rect, bool clipToParent){
|
||||
if (!hasIdentityMatrix()) {
|
||||
getMatrix().transform_rectangle((RectangleInt&)rect);//mapRect(rect);
|
||||
}
|
||||
rect.offset(mLeft, mTop);
|
||||
|
||||
View* parent = mParent;
|
||||
while (parent){// instanceof View) {
|
||||
View* parentView = (View*) parent;
|
||||
rect.offset(-parentView->mScrollX, -parentView->mScrollY);
|
||||
|
||||
if (clipToParent) {
|
||||
rect.left = std::max(rect.left, 0);
|
||||
rect.top = std::max(rect.top, 0);
|
||||
rect.width= std::min(rect.width,parentView->getWidth());//rect.right = std::min(rect.right, parentView->getWidth());
|
||||
rect.height=std::min(rect.height,parentView->getHeight());//rect.bottom = std::min(rect.bottom, parentView->getHeight());
|
||||
}
|
||||
if (!parentView->hasIdentityMatrix()) {
|
||||
parentView->getMatrix().transform_rectangle((RectangleInt&)rect);//mapRect(rect);
|
||||
}
|
||||
rect.offset(parentView->mLeft, parentView->mTop);
|
||||
parent = parentView->mParent;
|
||||
}
|
||||
/*if (parent instanceof ViewRootImpl) {
|
||||
ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
|
||||
rect.offset(0, -viewRootImpl.mCurScrollY);
|
||||
}*/
|
||||
rect.offset(mAttachInfo->mWindowLeft, mAttachInfo->mWindowTop);
|
||||
}
|
||||
|
||||
void View::getLocationOnScreen(int*outLocation){
|
||||
@ -1318,6 +1345,13 @@ void View::dispatchDetachedFromWindow(){
|
||||
onDetachedFromWindowInternal();
|
||||
InputMethodManager&imm=InputMethodManager::getInstance();
|
||||
imm.onViewDetachedFromWindow(this);
|
||||
|
||||
if(mListenerInfo){
|
||||
for(auto l:mListenerInfo->mOnAttachStateChangeListeners){
|
||||
if(l.onViewDetachedFromWindow)l.onViewDetachedFromWindow(*this);
|
||||
}
|
||||
}
|
||||
|
||||
if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
|
||||
std::vector<View*>&conts=mAttachInfo->mScrollContainers;
|
||||
auto it=std::find(conts.begin(),conts.end(),this);
|
||||
@ -2274,7 +2308,35 @@ void View::addOnLayoutChangeListener(OnLayoutChangeListener listener){
|
||||
}
|
||||
|
||||
void View::removeOnLayoutChangeListener(OnLayoutChangeListener listener){
|
||||
//mOnLayoutChangeListeners.push_back(listener);
|
||||
if(mListenerInfo){
|
||||
std::vector<View::OnLayoutChangeListener>&ls= mListenerInfo->mOnLayoutChangeListeners;
|
||||
auto it= std::find(ls.begin(),ls.end(),listener);
|
||||
ls.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void View::addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
|
||||
ListenerInfo* li = getListenerInfo();
|
||||
if (li) {
|
||||
std::vector<OnAttachStateChangeListener>&ls = li->mOnAttachStateChangeListeners;
|
||||
ls.push_back(listener);
|
||||
}
|
||||
}
|
||||
|
||||
static bool operator == (const View::OnAttachStateChangeListener& left, const View::OnAttachStateChangeListener& right){
|
||||
return (left.onViewAttachedToWindow==right.onViewAttachedToWindow) &&
|
||||
(left.onViewDetachedFromWindow==right.onViewDetachedFromWindow);
|
||||
}
|
||||
|
||||
void View::removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
|
||||
if (mListenerInfo == nullptr || mListenerInfo->mOnAttachStateChangeListeners.empty()) {
|
||||
return;
|
||||
}
|
||||
std::vector<OnAttachStateChangeListener>&ls = mListenerInfo->mOnAttachStateChangeListeners;
|
||||
auto it=std::find(ls.begin(),ls.end(),listener);
|
||||
if(it!=ls.end()){
|
||||
mListenerInfo->mOnAttachStateChangeListeners.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void View::startActivityForResult(Intent intent, int requestCode){
|
||||
@ -4237,6 +4299,8 @@ void View::getWindowVisibleDisplayFrame(Rect& outRect){
|
||||
// XXX This is really broken, and probably all needs to be done
|
||||
// in the window manager, and we need to know more about whether
|
||||
// we want the area behind or in front of the IME.
|
||||
const DisplayMetrics& metrics= mContext->getDisplayMetrics();
|
||||
outRect.set(0,0,metrics.widthPixels,metrics.heightPixels);
|
||||
Rect insets = mAttachInfo->mVisibleInsets;
|
||||
outRect.left += insets.left;
|
||||
outRect.top += insets.top;
|
||||
@ -4623,12 +4687,102 @@ ViewGroup*View::getRootView()const{
|
||||
return dynamic_cast<ViewGroup*>(parent);
|
||||
}
|
||||
|
||||
bool View::toGlobalMotionEvent(MotionEvent& ev){
|
||||
if (mAttachInfo == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Matrix m = identity_matrix();
|
||||
transformMatrixToGlobal(m);
|
||||
//ev.transform(m);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool View::toLocalMotionEvent(MotionEvent& ev){
|
||||
if (mAttachInfo == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Matrix m = identity_matrix();
|
||||
transformMatrixToLocal(m);
|
||||
//ev.transform(m);
|
||||
return true;
|
||||
}
|
||||
|
||||
void View::transformMatrixToGlobal(Matrix& matrix){
|
||||
#if 0
|
||||
ViewGroup* parent = mParent;
|
||||
if (parent instanceof View) {
|
||||
View* vp = (View) parent;
|
||||
vp->transformMatrixToGlobal(matrix);
|
||||
matrix.preTranslate(-vp.mScrollX, -vp.mScrollY);
|
||||
} else if (parent instanceof ViewRootImpl) {
|
||||
ViewRootImpl vr = (ViewRootImpl) parent;
|
||||
vr->transformMatrixToGlobal(matrix);
|
||||
matrix.preTranslate(0, -vr.mCurScrollY);
|
||||
}
|
||||
matrix.preTranslate(mLeft, mTop);
|
||||
if (!hasIdentityMatrix()) {
|
||||
matrix.preConcat(getMatrix());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void View::transformMatrixToLocal(Matrix& matrix){
|
||||
#if 0
|
||||
ViewGroup* parent = mParent;
|
||||
if (parent instanceof View) {
|
||||
View* vp = (View) parent;
|
||||
vp->transformMatrixToLocal(matrix);
|
||||
matrix.postTranslate(vp.mScrollX, vp.mScrollY);
|
||||
} else if (parent instanceof ViewRootImpl) {
|
||||
ViewRootImpl vr = (ViewRootImpl) parent;
|
||||
vr->transformMatrixToLocal(matrix);
|
||||
matrix.postTranslate(0, vr.mCurScrollY);
|
||||
}
|
||||
|
||||
matrix.postTranslate(-mLeft, -mTop);
|
||||
|
||||
if (!hasIdentityMatrix()) {
|
||||
matrix.postConcat(getInverseMatrix());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
View*View::focusSearch(int direction)const{
|
||||
if(mParent)
|
||||
mParent->focusSearch((View*)this,direction);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool View::requestRectangleOnScreen(Rect& rectangle, bool immediate){
|
||||
if (mParent == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
View* child = this;
|
||||
|
||||
RectF position;
|
||||
position.set(rectangle.left,rectangle.top,rectangle.width,rectangle.height);
|
||||
|
||||
ViewGroup* parent = mParent;
|
||||
bool scrolled = false;
|
||||
while (parent != nullptr) {
|
||||
rectangle.set((int) position.left, (int) position.top,
|
||||
(int) position.width, (int) position.height);
|
||||
|
||||
scrolled |= parent->requestChildRectangleOnScreen(child, rectangle, immediate);
|
||||
|
||||
//if (!(parent instanceof View)) { break; }
|
||||
// move it from child's content coordinate space to parent's content coordinate space
|
||||
position.offset(child->mLeft - child->getScrollX(), child->mTop -child->getScrollY());
|
||||
|
||||
child = parent;
|
||||
parent = child->getParent();
|
||||
}
|
||||
return scrolled;
|
||||
}
|
||||
|
||||
bool View::requestFocus(int direction){
|
||||
return requestFocus(direction,nullptr);
|
||||
}
|
||||
@ -5034,7 +5188,7 @@ void View::layout(int l, int t, int w, int h){
|
||||
}
|
||||
if(mListenerInfo){
|
||||
for(auto ls:mListenerInfo->mOnLayoutChangeListeners){
|
||||
ls(this,l, t, w, h,oldL,oldT,oldW,oldH);
|
||||
ls(*this,l, t, w, h,oldL,oldT,oldW,oldH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -323,10 +323,12 @@ public:
|
||||
DECLARE_UIEVENT(bool,OnContextClickListener,View&);
|
||||
DECLARE_UIEVENT(void,OnFocusChangeListener,View&,bool);
|
||||
DECLARE_UIEVENT(void,OnScrollChangeListener,View& v, int, int, int, int);
|
||||
DECLARE_UIEVENT(void,OnLayoutChangeListener,View* v, int left, int top, int width, int height,
|
||||
int oldLeft, int oldTop, int oldWidth, int oldHeight);
|
||||
typedef CallbackBase<void,View&,int,int,int,int,int,int,int,int>OnLayoutChangeListener;
|
||||
typedef CallbackBase<bool,View&,KeyEvent&>OnUnhandledKeyEventListener;
|
||||
|
||||
typedef struct{
|
||||
CallbackBase<void,View&>onViewAttachedToWindow;
|
||||
CallbackBase<void,View&>onViewDetachedFromWindow;
|
||||
}OnAttachStateChangeListener;
|
||||
private:
|
||||
friend ViewGroup;
|
||||
friend ViewPropertyAnimator;
|
||||
@ -767,6 +769,8 @@ public:
|
||||
virtual void setOnScrollChangeListener(OnScrollChangeListener l);
|
||||
void addOnLayoutChangeListener(OnLayoutChangeListener listener);
|
||||
void removeOnLayoutChangeListener(OnLayoutChangeListener listener);
|
||||
void addOnAttachStateChangeListener(OnAttachStateChangeListener listener);
|
||||
void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener);
|
||||
virtual bool performClick();
|
||||
virtual bool performLongClick();
|
||||
virtual bool performLongClick(int x,int y);
|
||||
@ -911,6 +915,7 @@ public:
|
||||
virtual bool restoreFocusInCluster(int direction);
|
||||
virtual bool restoreFocusNotInCluster();
|
||||
virtual bool restoreDefaultFocus();
|
||||
bool requestRectangleOnScreen(Rect& rectangle, bool immediate=false);
|
||||
void clearFocus();
|
||||
virtual View*findFocus();
|
||||
bool requestFocus(int direction=FOCUS_DOWN);
|
||||
@ -922,6 +927,10 @@ public:
|
||||
// Parent and children views
|
||||
virtual ViewGroup*getParent()const;
|
||||
ViewGroup*getRootView()const;
|
||||
bool toGlobalMotionEvent(MotionEvent& ev);
|
||||
bool toLocalMotionEvent(MotionEvent& ev);
|
||||
void transformMatrixToGlobal(Matrix& matrix);
|
||||
void transformMatrixToLocal(Matrix& matrix);
|
||||
void bringToFront();
|
||||
|
||||
virtual View* findViewById(int id);
|
||||
|
@ -1697,7 +1697,7 @@ void ViewGroup::invalidateChild(View*child,Rect&dirty){
|
||||
transformMatrix=childMatrix;
|
||||
}
|
||||
|
||||
transformMatrix.transform_rectangle((const RectangleInt&)dirty,(RectangleInt&)dirty);
|
||||
transformMatrix.transform_rectangle((RectangleInt&)dirty);
|
||||
LOGV("(1.%d,%d,%d,%d)-->(%d,%d,%d,%d) rotation=%f",boundingRect.left,boundingRect.top,boundingRect.width,boundingRect.height,
|
||||
dirty.left,dirty.top,dirty.width,dirty.height,child->getRotation());
|
||||
}
|
||||
@ -1726,7 +1726,7 @@ void ViewGroup::invalidateChild(View*child,Rect&dirty){
|
||||
parent = parent->invalidateChildInParent(location, dirty);
|
||||
if ( view && !view->hasIdentityMatrix() ) { // Account for transform on current parent
|
||||
Matrix m = view->getMatrix();
|
||||
m.transform_rectangle((const RectangleInt&)dirty,(RectangleInt&)dirty);
|
||||
m.transform_rectangle((RectangleInt&)dirty);
|
||||
}
|
||||
} while (parent);
|
||||
|
||||
|
560
src/gui/widget/popupwindow.cc
Normal file → Executable file
560
src/gui/widget/popupwindow.cc
Normal file → Executable file
@ -60,6 +60,9 @@ PopupWindow::PopupWindow(View* contentView, int width, int height, bool focusabl
|
||||
PopupWindow::PopupWindow(int width, int height):PopupWindow(nullptr,width,height){
|
||||
}
|
||||
|
||||
PopupWindow::~PopupWindow(){
|
||||
}
|
||||
|
||||
void PopupWindow::init(){
|
||||
mIsShowing = false;
|
||||
mIsDropdown= false;
|
||||
@ -73,6 +76,7 @@ void PopupWindow::init(){
|
||||
mLayoutInsetDecor = false;
|
||||
mAttachedInDecor = false;
|
||||
mAttachedInDecorSet= false;
|
||||
mEpicenterBounds.set(0,0,0,0);
|
||||
|
||||
mParentRootView = nullptr;
|
||||
mAnchor = nullptr;
|
||||
@ -81,6 +85,15 @@ void PopupWindow::init(){
|
||||
mBackgroundView = nullptr;
|
||||
mAboveAnchorBackgroundDrawable = nullptr;
|
||||
mBelowAnchorBackgroundDrawable = nullptr;
|
||||
|
||||
mOnLayoutChangeListener=[this](View&v,int,int,int,int,int,int,int,int){
|
||||
//alignToAnchor();
|
||||
};
|
||||
|
||||
mOnAnchorRootDetachedListener.onViewAttachedToWindow=[](View&){/*nothing*/};
|
||||
mOnAnchorRootDetachedListener.onViewDetachedFromWindow=[this](View&v){
|
||||
mIsAnchorRootAttached = false;
|
||||
};
|
||||
}
|
||||
|
||||
void PopupWindow::setEpicenterBounds(const Rect& bounds) {
|
||||
@ -183,6 +196,31 @@ void PopupWindow::setOutsideTouchable(bool touchable){
|
||||
mOutsideTouchable=touchable;
|
||||
}
|
||||
|
||||
bool PopupWindow::isClippingEnabled(){
|
||||
return mClippingEnabled;
|
||||
}
|
||||
|
||||
void PopupWindow::setClippingEnabled(bool enabled){
|
||||
mClippingEnabled = enabled;
|
||||
}
|
||||
|
||||
bool PopupWindow::isClippedToScreen(){
|
||||
return mClipToScreen;
|
||||
}
|
||||
|
||||
void PopupWindow::setIsClippedToScreen(bool enabled){
|
||||
mClipToScreen = enabled;
|
||||
}
|
||||
|
||||
bool PopupWindow::isSplitTouchEnabled(){
|
||||
return mSplitTouchEnabled == 1;
|
||||
}
|
||||
|
||||
void PopupWindow::setSplitTouchEnabled(bool enabled){
|
||||
mSplitTouchEnabled = enabled ? 1 : 0;
|
||||
}
|
||||
|
||||
|
||||
bool PopupWindow::isLayoutInScreenEnabled()const{
|
||||
return mLayoutInScreen;
|
||||
}
|
||||
@ -191,6 +229,14 @@ void PopupWindow::setLayoutInScreenEnabled(bool enabled){
|
||||
mLayoutInScreen=enabled;
|
||||
}
|
||||
|
||||
bool PopupWindow::isLaidOutInScreen(){
|
||||
return mLayoutInScreen;
|
||||
}
|
||||
|
||||
void PopupWindow::setIsLaidOutInScreen(bool enabled){
|
||||
mLayoutInScreen = enabled;
|
||||
}
|
||||
|
||||
bool PopupWindow::isAttachedInDecor()const{
|
||||
return mAttachedInDecor;
|
||||
}
|
||||
@ -208,6 +254,18 @@ bool PopupWindow::isLayoutInsetDecor()const{
|
||||
return mLayoutInsetDecor;
|
||||
}
|
||||
|
||||
void PopupWindow::setWindowLayoutType(int layoutType){
|
||||
mWindowLayoutType = layoutType;
|
||||
}
|
||||
|
||||
int PopupWindow::getWindowLayoutType(){
|
||||
return mWindowLayoutType;
|
||||
}
|
||||
|
||||
bool PopupWindow::isTouchModal(){
|
||||
return !mNotTouchModal;
|
||||
}
|
||||
|
||||
void PopupWindow::setTouchModal(bool touchModal){
|
||||
mNotTouchModal =!touchModal;
|
||||
}
|
||||
@ -249,6 +307,23 @@ int PopupWindow::getWidth(){
|
||||
}
|
||||
|
||||
void PopupWindow::showAtLocation(View* parent, int gravity, int x, int y){
|
||||
if (isShowing() || mContentView == nullptr) {
|
||||
return;
|
||||
}
|
||||
//TransitionManager.endTransitions(mDecorView);
|
||||
|
||||
detachFromAnchor();
|
||||
|
||||
mIsShowing = true;
|
||||
mIsDropdown = false;
|
||||
mGravity = gravity;
|
||||
|
||||
WindowManager::LayoutParams p=createPopupLayoutParams(0);
|
||||
preparePopup(&p);
|
||||
|
||||
p.x = x;
|
||||
p.y = y;
|
||||
invokePopup(&p);
|
||||
}
|
||||
|
||||
void PopupWindow::showAsDropDown(View* anchor){
|
||||
@ -271,19 +346,19 @@ void PopupWindow::showAsDropDown(View* anchor, int xoff, int yoff,int gravity){
|
||||
mIsShowing = true;
|
||||
mIsDropdown = true;
|
||||
|
||||
LayoutParams* p=nullptr;//=createPopupLayoutParams(anchor.getApplicationWindowToken());
|
||||
preparePopup(p);
|
||||
WindowManager::LayoutParams p=createPopupLayoutParams(0);//anchor.getApplicationWindowToken());
|
||||
p.x = xoff;
|
||||
p.y = yoff;
|
||||
preparePopup(&p);
|
||||
|
||||
bool aboveAnchor =false;
|
||||
mDecorView->setPos(xoff,yoff);
|
||||
//findDropDownPosition(anchor, p, xoff, yoff,
|
||||
//p.width, p.height, gravity, mAllowScrollingAnchorParent);
|
||||
bool aboveAnchor = findDropDownPosition(anchor,&p, xoff, yoff,
|
||||
p.width, p.height, gravity, mAllowScrollingAnchorParent);
|
||||
updateAboveAnchor(aboveAnchor);
|
||||
//p.accessibilityIdOfAnchor = (anchor) ? anchor->getAccessibilityViewId() : -1;
|
||||
invokePopup(nullptr);
|
||||
invokePopup(&p);
|
||||
}
|
||||
|
||||
void PopupWindow::preparePopup(LayoutParams*p){
|
||||
void PopupWindow::preparePopup(WindowManager::LayoutParams*p){
|
||||
//if (mDecorView) mDecorView->cancelTransitions();
|
||||
|
||||
// When a background is available, we embed the content view within
|
||||
@ -338,7 +413,7 @@ PopupWindow::PopupDecorView* PopupWindow::createDecorView(View* contentView){
|
||||
PopupDecorView* decorView = new PopupDecorView(mWidth,mHeight);
|
||||
decorView->addView(contentView, LayoutParams::MATCH_PARENT, height);
|
||||
//decorView->setClipChildren(false);
|
||||
decorView->setClipToPadding(false);
|
||||
//decorView->setClipToPadding(false);
|
||||
return decorView;
|
||||
}
|
||||
|
||||
@ -363,8 +438,14 @@ void PopupWindow::updateAboveAnchor(bool aboveAnchor){
|
||||
}
|
||||
}
|
||||
|
||||
void PopupWindow::invokePopup(LayoutParams* p){
|
||||
|
||||
void PopupWindow::invokePopup(WindowManager::LayoutParams* p){
|
||||
//mDecorView->setFitsSystemWindows(mLayoutInsetDecor);
|
||||
setLayoutDirectionFromAnchor();
|
||||
WindowManager::getInstance().moveWindow(mDecorView,p->x,p->y);
|
||||
//mWindowManager->addView(mDecorView, p);
|
||||
/*if (mEnterTransition != nullptr) {
|
||||
mDecorView->requestEnterTransition(mEnterTransition);
|
||||
}*/
|
||||
}
|
||||
|
||||
void PopupWindow::setLayoutDirectionFromAnchor() {
|
||||
@ -393,6 +474,240 @@ int PopupWindow::getMaxAvailableHeight(View* anchor){
|
||||
return getMaxAvailableHeight(anchor, 0,false);
|
||||
}
|
||||
|
||||
WindowManager::LayoutParams PopupWindow::createPopupLayoutParams(long token){
|
||||
WindowManager::LayoutParams p;// = new WindowManager.LayoutParams();
|
||||
|
||||
// These gravity settings put the view at the top left corner of the
|
||||
// screen. The view is then positioned to the appropriate location by
|
||||
// setting the x and y offsets to match the anchor's bottom-left
|
||||
// corner.
|
||||
p.gravity = computeGravity();
|
||||
p.flags = computeFlags(p.flags);
|
||||
/*p.type = mWindowLayoutType;
|
||||
p.token = token;
|
||||
p.softInputMode = mSoftInputMode;
|
||||
p.windowAnimations = computeAnimationResource();
|
||||
|
||||
if (mBackground != nullptr) {
|
||||
p.format = mBackground.getOpacity();
|
||||
} else {
|
||||
p.format = PixelFormat.TRANSLUCENT;
|
||||
}*/
|
||||
|
||||
if (mHeightMode < 0) {
|
||||
p.height = mLastHeight = mHeightMode;
|
||||
} else {
|
||||
p.height = mLastHeight = mHeight;
|
||||
}
|
||||
|
||||
if (mWidthMode < 0) {
|
||||
p.width = mLastWidth = mWidthMode;
|
||||
} else {
|
||||
p.width = mLastWidth = mWidth;
|
||||
}
|
||||
|
||||
/*p.privateFlags = PRIVATE_FLAG_WILL_NOT_REPLACE_ON_RELAUNCH
|
||||
| PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME;
|
||||
|
||||
// Used for debugging.
|
||||
p.setTitle("PopupWindow:" + Integer.toHexString(hashCode()));*/
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
int PopupWindow::computeFlags(int curFlags){
|
||||
return curFlags;
|
||||
}
|
||||
|
||||
bool PopupWindow::tryFitVertical(WindowManager::LayoutParams* outParams, int yOffset, int height,
|
||||
int anchorHeight, int drawingLocationY, int screenLocationY, int displayFrameTop,
|
||||
int displayFrameBottom, bool allowResize){
|
||||
int winOffsetY = screenLocationY - drawingLocationY;
|
||||
int anchorTopInScreen = outParams->y + winOffsetY;
|
||||
int spaceBelow = displayFrameBottom - anchorTopInScreen;
|
||||
if (anchorTopInScreen >= displayFrameTop && height <= spaceBelow) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int spaceAbove = anchorTopInScreen - anchorHeight - displayFrameTop;
|
||||
if (height <= spaceAbove) {
|
||||
// Move everything up.
|
||||
if (mOverlapAnchor) {
|
||||
yOffset += anchorHeight;
|
||||
}
|
||||
outParams->y = drawingLocationY - height + yOffset;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (positionInDisplayVertical(outParams, height, drawingLocationY, screenLocationY,
|
||||
displayFrameTop, displayFrameBottom, allowResize)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PopupWindow::positionInDisplayVertical(WindowManager::LayoutParams* outParams, int height,
|
||||
int drawingLocationY, int screenLocationY, int displayFrameTop, int displayFrameBottom,
|
||||
bool canResize){
|
||||
bool fitsInDisplay = true;
|
||||
int winOffsetY = screenLocationY - drawingLocationY;
|
||||
outParams->y += winOffsetY;
|
||||
outParams->height = height;
|
||||
|
||||
int bottom = outParams->y + height;
|
||||
if (bottom > displayFrameBottom) {
|
||||
// The popup is too far down, move it back in.
|
||||
outParams->y -= bottom - displayFrameBottom;
|
||||
}
|
||||
|
||||
if (outParams->y < displayFrameTop) {
|
||||
// The popup is too far up, move it back in and clip if
|
||||
// it's still too large.
|
||||
outParams->y = displayFrameTop;
|
||||
|
||||
int displayFrameHeight = displayFrameBottom - displayFrameTop;
|
||||
if (canResize && height > displayFrameHeight) {
|
||||
outParams->height = displayFrameHeight;
|
||||
} else {
|
||||
fitsInDisplay = false;
|
||||
}
|
||||
}
|
||||
outParams->y -= winOffsetY;
|
||||
return fitsInDisplay;
|
||||
}
|
||||
|
||||
bool PopupWindow::tryFitHorizontal(WindowManager::LayoutParams* outParams, int xOffset, int width,
|
||||
int anchorWidth, int drawingLocationX, int screenLocationX, int displayFrameLeft,
|
||||
int displayFrameRight, bool allowResize){
|
||||
int winOffsetX = screenLocationX - drawingLocationX;
|
||||
int anchorLeftInScreen = outParams->x + winOffsetX;
|
||||
int spaceRight = displayFrameRight - anchorLeftInScreen;
|
||||
if (anchorLeftInScreen >= displayFrameLeft && width <= spaceRight) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (positionInDisplayHorizontal(outParams, width, drawingLocationX, screenLocationX,
|
||||
displayFrameLeft, displayFrameRight, allowResize)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PopupWindow::positionInDisplayHorizontal(WindowManager::LayoutParams* outParams, int width,
|
||||
int drawingLocationX, int screenLocationX, int displayFrameLeft, int displayFrameRight,
|
||||
bool canResize){
|
||||
bool fitsInDisplay = true;
|
||||
// Use screen coordinates for comparison against display frame.
|
||||
int winOffsetX = screenLocationX - drawingLocationX;
|
||||
outParams->x += winOffsetX;
|
||||
|
||||
int right = outParams->x + width;
|
||||
if (right > displayFrameRight) {
|
||||
// The popup is too far right, move it back in.
|
||||
outParams->x -= right - displayFrameRight;
|
||||
}
|
||||
|
||||
if (outParams->x < displayFrameLeft) {
|
||||
// The popup is too far left, move it back in and clip if it's
|
||||
// still too large.
|
||||
outParams->x = displayFrameLeft;
|
||||
|
||||
int displayFrameWidth = displayFrameRight - displayFrameLeft;
|
||||
if (canResize && width > displayFrameWidth) {
|
||||
outParams->width = displayFrameWidth;
|
||||
} else {
|
||||
fitsInDisplay = false;
|
||||
}
|
||||
}
|
||||
outParams->x -= winOffsetX;
|
||||
return fitsInDisplay;
|
||||
}
|
||||
|
||||
bool PopupWindow::findDropDownPosition(View* anchor,WindowManager::LayoutParams* outParams,
|
||||
int xOffset, int yOffset, int width, int height, int gravity, bool allowScroll){
|
||||
int anchorHeight = anchor->getHeight();
|
||||
int anchorWidth = anchor->getWidth();
|
||||
if (mOverlapAnchor) {
|
||||
yOffset -= anchorHeight;
|
||||
}
|
||||
|
||||
// Initially, align to the bottom-left corner of the anchor plus offsets.
|
||||
int appScreenLocation[2];
|
||||
View* appRootView = anchor->getRootView();//getAppRootView(anchor);
|
||||
appRootView->getLocationOnScreen(appScreenLocation);
|
||||
|
||||
int screenLocation[2];
|
||||
anchor->getLocationOnScreen(screenLocation);
|
||||
|
||||
int drawingLocation[2];
|
||||
drawingLocation[0] = screenLocation[0] - appScreenLocation[0];
|
||||
drawingLocation[1] = screenLocation[1] - appScreenLocation[1];
|
||||
outParams->x = drawingLocation[0] + xOffset;
|
||||
outParams->y = drawingLocation[1] + anchorHeight + yOffset;
|
||||
|
||||
Rect displayFrame;
|
||||
appRootView->getWindowVisibleDisplayFrame(displayFrame);
|
||||
if (width == LayoutParams::MATCH_PARENT) {
|
||||
width = displayFrame.width;
|
||||
}
|
||||
if (height == LayoutParams::MATCH_PARENT) {
|
||||
height = displayFrame.height;
|
||||
}
|
||||
|
||||
// Let the window manager know to align the top to y.
|
||||
outParams->gravity = computeGravity();
|
||||
outParams->width = width;
|
||||
outParams->height = height;
|
||||
|
||||
// If we need to adjust for gravity RIGHT, align to the bottom-right
|
||||
// corner of the anchor (still accounting for offsets).
|
||||
int hgrav = Gravity::getAbsoluteGravity(gravity, anchor->getLayoutDirection())
|
||||
& Gravity::HORIZONTAL_GRAVITY_MASK;
|
||||
if (hgrav == Gravity::RIGHT) {
|
||||
outParams->x -= width - anchorWidth;
|
||||
}
|
||||
|
||||
// First, attempt to fit the popup vertically without resizing.
|
||||
bool fitsVertical = tryFitVertical(outParams, yOffset, height,
|
||||
anchorHeight, drawingLocation[1], screenLocation[1], displayFrame.top,
|
||||
displayFrame.bottom(), false);
|
||||
|
||||
// Next, attempt to fit the popup horizontally without resizing.
|
||||
bool fitsHorizontal = tryFitHorizontal(outParams, xOffset, width,
|
||||
anchorWidth, drawingLocation[0], screenLocation[0], displayFrame.left,
|
||||
displayFrame.right(), false);
|
||||
|
||||
// If the popup still doesn't fit, attempt to scroll the parent.
|
||||
if (!fitsVertical || !fitsHorizontal) {
|
||||
int scrollX = anchor->getScrollX();
|
||||
int scrollY = anchor->getScrollY();
|
||||
Rect r = {scrollX, scrollY, width + xOffset,
|
||||
height + anchorHeight + yOffset};
|
||||
if (allowScroll && anchor->requestRectangleOnScreen(r, true)) {
|
||||
// Reset for the new anchor position.
|
||||
anchor->getLocationOnScreen(screenLocation);
|
||||
drawingLocation[0] = screenLocation[0] - appScreenLocation[0];
|
||||
drawingLocation[1] = screenLocation[1] - appScreenLocation[1];
|
||||
outParams->x = drawingLocation[0] + xOffset;
|
||||
outParams->y = drawingLocation[1] + anchorHeight + yOffset;
|
||||
// Preserve the gravity adjustment.
|
||||
if (hgrav == Gravity::RIGHT) {
|
||||
outParams->x -= width - anchorWidth;
|
||||
}
|
||||
}
|
||||
// Try to fit the popup again and allowing resizing.
|
||||
tryFitVertical(outParams, yOffset, height, anchorHeight, drawingLocation[1],
|
||||
screenLocation[1], displayFrame.top, displayFrame.bottom(), mClipToScreen);
|
||||
tryFitHorizontal(outParams, xOffset, width, anchorWidth, drawingLocation[0],
|
||||
screenLocation[0], displayFrame.left, displayFrame.right(), mClipToScreen);
|
||||
}
|
||||
|
||||
// Return whether the popup's top edge is above the anchor's top edge.
|
||||
return outParams->y < drawingLocation[1];
|
||||
}
|
||||
|
||||
int PopupWindow::getMaxAvailableHeight(View* anchor, int yOffset,bool ignoreBottomDecorations){
|
||||
Rect displayFrame;
|
||||
Rect visibleDisplayFrame;
|
||||
@ -440,6 +755,94 @@ void PopupWindow::dismiss(){
|
||||
if (!isShowing() /*|| isTransitioningToDismiss()*/) {
|
||||
return;
|
||||
}
|
||||
PopupDecorView* decorView = mDecorView;
|
||||
View* contentView = mContentView;
|
||||
|
||||
ViewGroup* contentHolder;
|
||||
ViewGroup* contentParent = contentView->getParent();
|
||||
contentHolder = ((ViewGroup*) contentParent);
|
||||
|
||||
// Ensure any ongoing or pending transitions are canceled.
|
||||
//decorView->cancelTransitions();
|
||||
|
||||
mIsShowing = false;
|
||||
mIsTransitioningToDismiss = true;
|
||||
// This method may be called as part of window detachment, in which
|
||||
// case the anchor view (and its root) will still return true from
|
||||
// isAttachedToWindow() during execution of this method; however, we
|
||||
// can expect the OnAttachStateChangeListener to have been called prior
|
||||
// to executing this method, so we can rely on that instead.
|
||||
/*Transition exitTransition = mExitTransition;
|
||||
if (exitTransition && decorView->isLaidOut()
|
||||
&& (mIsAnchorRootAttached || mAnchorRoot == nullptr)) {
|
||||
// The decor view is non-interactive and non-IME-focusable during exit transitions.
|
||||
LayoutParams p = (LayoutParams) decorView.getLayoutParams();
|
||||
p.flags |= LayoutParams.FLAG_NOT_TOUCHABLE;
|
||||
p.flags |= LayoutParams.FLAG_NOT_FOCUSABLE;
|
||||
p.flags &= ~LayoutParams.FLAG_ALT_FOCUSABLE_IM;
|
||||
mWindowManager.updateViewLayout(decorView, p);
|
||||
|
||||
View anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
|
||||
Rect epicenter = getTransitionEpicenter();
|
||||
|
||||
// Once we start dismissing the decor view, all state (including
|
||||
// the anchor root) needs to be moved to the decor view since we
|
||||
// may open another popup while it's busy exiting.
|
||||
decorView.startExitTransition(exitTransition, anchorRoot, epicenter,
|
||||
new TransitionListenerAdapter() {
|
||||
@Override
|
||||
public void onTransitionEnd(Transition transition) {
|
||||
dismissImmediate(decorView, contentHolder, contentView);
|
||||
}
|
||||
});
|
||||
} else */{
|
||||
dismissImmediate(decorView, contentHolder, contentView);
|
||||
}
|
||||
|
||||
// Clears the anchor view.
|
||||
detachFromAnchor();
|
||||
if (mOnDismissListener != nullptr) {
|
||||
mOnDismissListener();
|
||||
}
|
||||
}
|
||||
|
||||
Rect PopupWindow::getTransitionEpicenter(){
|
||||
if (mAnchor == nullptr || mDecorView == nullptr) {
|
||||
return Rect::MakeWH(0,0);
|
||||
}
|
||||
|
||||
int anchorLocation[2],popupLocation[2];
|
||||
mAnchor->getLocationOnScreen(anchorLocation);
|
||||
mDecorView->getLocationOnScreen(popupLocation);
|
||||
|
||||
// Compute the position of the anchor relative to the popup.
|
||||
Rect bounds = {0, 0, mAnchor->getWidth(), mAnchor->getHeight()};
|
||||
bounds.offset(anchorLocation[0] - popupLocation[0], anchorLocation[1] - popupLocation[1]);
|
||||
|
||||
// Use anchor-relative epicenter, if specified.
|
||||
if (!mEpicenterBounds.empty()){// != null) {
|
||||
int offsetX = bounds.left;
|
||||
int offsetY = bounds.top;
|
||||
bounds=mEpicenterBounds;//set(mEpicenterBounds);
|
||||
bounds.offset(offsetX, offsetY);
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
void PopupWindow::dismissImmediate(View* decorView, ViewGroup* contentHolder, View* contentView){
|
||||
if (decorView->getParent()!=nullptr) {
|
||||
//mWindowManager.removeViewImmediate(decorView);
|
||||
}
|
||||
|
||||
if (contentHolder != nullptr) {
|
||||
contentHolder->removeView(contentView);
|
||||
}
|
||||
|
||||
// This needs to stay until after all transitions have ended since we
|
||||
// need the reference to cancel transitions in preparePopup().
|
||||
mDecorView = nullptr;
|
||||
mBackgroundView = nullptr;
|
||||
mIsTransitioningToDismiss = false;
|
||||
}
|
||||
|
||||
void PopupWindow::setOnDismissListener(OnDismissListener onDismissListener) {
|
||||
@ -455,36 +858,34 @@ void PopupWindow::update(){
|
||||
if (!isShowing() || !hasContentView()) {
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
Window::LayoutParams* p = getDecorViewLayoutParams();
|
||||
WindowManager::LayoutParams* p = getDecorViewLayoutParams();
|
||||
|
||||
bool bUpdate = false;
|
||||
|
||||
int newAnim = computeAnimationResource();
|
||||
/*int newAnim = computeAnimationResource();
|
||||
if (newAnim != p.windowAnimations) {
|
||||
p.windowAnimations = newAnim;
|
||||
bUpdate = true;
|
||||
}
|
||||
}*/
|
||||
|
||||
int newFlags = computeFlags(p.flags);
|
||||
if (newFlags != p.flags) {
|
||||
p.flags = newFlags;
|
||||
int newFlags = computeFlags(p->flags);
|
||||
if (newFlags != p->flags) {
|
||||
p->flags = newFlags;
|
||||
bUpdate = true;
|
||||
}
|
||||
|
||||
int newGravity = computeGravity();
|
||||
if (newGravity != p.gravity) {
|
||||
p.gravity = newGravity;
|
||||
if (newGravity != p->gravity) {
|
||||
p->gravity = newGravity;
|
||||
bUpdate = true;
|
||||
}
|
||||
|
||||
if (bUpdate) {
|
||||
update(mAnchor, p);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PopupWindow::update(View* anchor,LayoutParams* params) {
|
||||
void PopupWindow::update(View* anchor,WindowManager::LayoutParams* params) {
|
||||
setLayoutDirectionFromAnchor();
|
||||
// mWindowManager.updateViewLayout(mDecorView, params);
|
||||
}
|
||||
@ -493,7 +894,7 @@ void PopupWindow::update(int width, int height){
|
||||
update(0,0/*getLeft(), getTop()*/, width, height);
|
||||
}
|
||||
|
||||
void PopupWindow::update(int x, int y, int width, int height){
|
||||
void PopupWindow::update(int x, int y, int width, int height,bool force){
|
||||
if (width >= 0) {
|
||||
mLastWidth = width;
|
||||
setWidth(width);
|
||||
@ -509,49 +910,48 @@ void PopupWindow::update(int x, int y, int width, int height){
|
||||
}
|
||||
|
||||
|
||||
bool updated = true;//force;
|
||||
#if 0
|
||||
WindowManager.LayoutParams p = getDecorViewLayoutParams();
|
||||
bool updated = force;
|
||||
|
||||
WindowManager::LayoutParams* p = getDecorViewLayoutParams();
|
||||
int finalWidth = mWidthMode < 0 ? mWidthMode : mLastWidth;
|
||||
if (width != -1 && p.width != finalWidth) {
|
||||
p.width = mLastWidth = finalWidth;
|
||||
if (width != -1 && p->width != finalWidth) {
|
||||
p->width = mLastWidth = finalWidth;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
int finalHeight = mHeightMode < 0 ? mHeightMode : mLastHeight;
|
||||
if (height != -1 && p.height != finalHeight) {
|
||||
p.height = mLastHeight = finalHeight;
|
||||
if (height != -1 && p->height != finalHeight) {
|
||||
p->height = mLastHeight = finalHeight;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (p.x != x) {
|
||||
p.x = x;
|
||||
if (p->x != x) {
|
||||
p->x = x;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
if (p.y != y) {
|
||||
p.y = y;
|
||||
if (p->y != y) {
|
||||
p->y = y;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
int newAnim = computeAnimationResource();
|
||||
if (newAnim != p.windowAnimations) {
|
||||
p.windowAnimations = newAnim;
|
||||
/*int newAnim = computeAnimationResource();
|
||||
if (newAnim != p->windowAnimations) {
|
||||
p->windowAnimations = newAnim;
|
||||
updated = true;
|
||||
}
|
||||
}*/
|
||||
|
||||
const int newFlags = computeFlags(p.flags);
|
||||
if (newFlags != p.flags) {
|
||||
p.flags = newFlags;
|
||||
const int newFlags = computeFlags(p->flags);
|
||||
if (newFlags != p->flags) {
|
||||
p->flags = newFlags;
|
||||
updated = true;
|
||||
}
|
||||
|
||||
const int newGravity = computeGravity();
|
||||
if (newGravity != p.gravity) {
|
||||
p.gravity = newGravity;
|
||||
if (newGravity != p->gravity) {
|
||||
p->gravity = newGravity;
|
||||
updated = true;
|
||||
}
|
||||
#endif
|
||||
View* anchor = nullptr;
|
||||
int newAccessibilityIdOfAnchor = -1;
|
||||
|
||||
@ -566,10 +966,59 @@ void PopupWindow::update(int x, int y, int width, int height){
|
||||
}*/
|
||||
|
||||
if (updated) {
|
||||
//update(anchor, p);
|
||||
update(anchor, p);
|
||||
}
|
||||
}
|
||||
|
||||
void PopupWindow::update(View* anchor, bool updateLocation, int xoff, int yoff, int width, int height){
|
||||
if (!isShowing() || !hasContentView()) {
|
||||
return;
|
||||
}
|
||||
|
||||
View* oldAnchor = mAnchor;
|
||||
int gravity = mAnchoredGravity;
|
||||
|
||||
bool needsUpdate = updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff);
|
||||
if (oldAnchor == nullptr || oldAnchor != anchor || (needsUpdate && !mIsDropdown)) {
|
||||
attachToAnchor(anchor, xoff, yoff, gravity);
|
||||
} else if (needsUpdate) {
|
||||
// No need to register again if this is a DropDown, showAsDropDown already did.
|
||||
mAnchorXoff = xoff;
|
||||
mAnchorYoff = yoff;
|
||||
}
|
||||
|
||||
WindowManager::LayoutParams* p = getDecorViewLayoutParams();
|
||||
int oldGravity = p->gravity;
|
||||
int oldWidth = p->width;
|
||||
int oldHeight = p->height;
|
||||
int oldX = p->x;
|
||||
int oldY = p->y;
|
||||
|
||||
// If an explicit width/height has not specified, use the most recent
|
||||
// explicitly specified value (either from setWidth/Height or update).
|
||||
if (width < 0) {
|
||||
width = mWidth;
|
||||
}
|
||||
if (height < 0) {
|
||||
height = mHeight;
|
||||
}
|
||||
|
||||
bool aboveAnchor = findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff,
|
||||
width, height, gravity, mAllowScrollingAnchorParent);
|
||||
updateAboveAnchor(aboveAnchor);
|
||||
|
||||
bool paramsChanged = oldGravity != p->gravity || oldX != p->x || oldY != p->y
|
||||
|| oldWidth != p->width || oldHeight != p->height;
|
||||
|
||||
// If width and mWidth were both < 0 then we have a MATCH_PARENT or
|
||||
// WRAP_CONTENT case. findDropDownPosition will have resolved this to
|
||||
// absolute values, but we don't want to update mWidth/mHeight to these
|
||||
// absolute values.
|
||||
int newWidth = width < 0 ? width : p->width;
|
||||
int newHeight = height < 0 ? height : p->height;
|
||||
update(p->x, p->y, newWidth, newHeight, paramsChanged);
|
||||
}
|
||||
|
||||
bool PopupWindow::hasContentView()const{
|
||||
return mContentView!=nullptr;
|
||||
}
|
||||
@ -578,6 +1027,10 @@ bool PopupWindow::hasDecorView()const{
|
||||
return mDecorView!=nullptr;
|
||||
}
|
||||
|
||||
WindowManager::LayoutParams* PopupWindow::getDecorViewLayoutParams() {
|
||||
return (WindowManager::LayoutParams*) mDecorView->getLayoutParams();
|
||||
}
|
||||
|
||||
void PopupWindow::detachFromAnchor(){
|
||||
View* anchor = mAnchor;//getAnchor();
|
||||
/*if (anchor) {
|
||||
@ -586,11 +1039,11 @@ void PopupWindow::detachFromAnchor(){
|
||||
anchor->removeOnAttachStateChangeListener(mOnAnchorDetachedListener);
|
||||
}*/
|
||||
|
||||
/*View* anchorRoot = mAnchorRoot != null ? mAnchorRoot.get() : null;
|
||||
View* anchorRoot = mAnchorRoot;// != null ? mAnchorRoot.get() : null;
|
||||
if (anchorRoot != nullptr) {
|
||||
anchorRoot->removeOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
|
||||
anchorRoot->removeOnLayoutChangeListener(mOnLayoutChangeListener);
|
||||
}*/
|
||||
}
|
||||
|
||||
mAnchor = nullptr;
|
||||
mAnchorRoot = nullptr;
|
||||
@ -607,8 +1060,8 @@ void PopupWindow::attachToAnchor(View* anchor, int xoff, int yoff, int gravity){
|
||||
//anchor.addOnAttachStateChangeListener(mOnAnchorDetachedListener);
|
||||
|
||||
View* anchorRoot = anchor->getRootView();
|
||||
//anchorRoot->addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
|
||||
//anchorRoot->addOnLayoutChangeListener(mOnLayoutChangeListener);
|
||||
anchorRoot->addOnAttachStateChangeListener(mOnAnchorRootDetachedListener);
|
||||
anchorRoot->addOnLayoutChangeListener(mOnLayoutChangeListener);
|
||||
|
||||
mAnchor = anchor;//new WeakReference<>(anchor);
|
||||
mAnchorRoot = anchorRoot;//new WeakReference<>(anchorRoot);
|
||||
@ -620,6 +1073,15 @@ void PopupWindow::attachToAnchor(View* anchor, int xoff, int yoff, int gravity){
|
||||
mAnchoredGravity = gravity;
|
||||
}
|
||||
|
||||
void PopupWindow::alignToAnchor() {
|
||||
if (mAnchor && mAnchor->isAttachedToWindow() && hasDecorView()) {
|
||||
WindowManager::LayoutParams* p = getDecorViewLayoutParams();
|
||||
updateAboveAnchor(findDropDownPosition(mAnchor, p, mAnchorXoff, mAnchorYoff,
|
||||
p->width, p->height, mAnchoredGravity, false));
|
||||
update(p->x, p->y, -1, -1, true);
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
PopupWindow::PopupDecorView::PopupDecorView(int w,int h)
|
||||
:Window(0,0,w,h){
|
||||
|
41
src/gui/widget/popupwindow.h
Normal file → Executable file
41
src/gui/widget/popupwindow.h
Normal file → Executable file
@ -2,6 +2,7 @@
|
||||
#define __POPUP_WINDOW_H__
|
||||
#include <widget/framelayout.h>
|
||||
#include <widget/cdwindow.h>
|
||||
#include <core/windowmanager.h>
|
||||
namespace cdroid{
|
||||
class PopupWindow{
|
||||
public:
|
||||
@ -88,6 +89,9 @@ private:
|
||||
int mGravity = Gravity::NO_GRAVITY;
|
||||
View* mAnchor;
|
||||
View* mAnchorRoot;
|
||||
View::OnAttachStateChangeListener mOnAnchorRootDetachedListener;
|
||||
//View::OnScrollChangedListener mOnScrollChangedListener;
|
||||
View::OnLayoutChangeListener mOnLayoutChangeListener;
|
||||
bool mIsAnchorRootAttached;
|
||||
int mAnchorXoff;
|
||||
int mAnchorYoff;
|
||||
@ -98,9 +102,21 @@ private:
|
||||
private:
|
||||
void init();
|
||||
int computeGravity();
|
||||
int computeFlags(int curFlags);
|
||||
PopupDecorView* createDecorView(View* contentView);
|
||||
void invokePopup(LayoutParams* p);
|
||||
void invokePopup(WindowManager::LayoutParams* p);
|
||||
void setLayoutDirectionFromAnchor();
|
||||
void update(View* anchor, bool updateLocation, int xoff, int yoff, int width, int height);
|
||||
bool tryFitVertical(WindowManager::LayoutParams* outParams, int yOffset, int height, int anchorHeight,
|
||||
int drawingLocationY, int screenLocationY, int displayFrameTop,int displayFrameBottom, bool allowResize);
|
||||
bool positionInDisplayVertical(WindowManager::LayoutParams* outParams, int height, int drawingLocationY,
|
||||
int screenLocationY, int displayFrameTop, int displayFrameBottom, bool canResize);
|
||||
bool tryFitHorizontal(WindowManager::LayoutParams* outParams, int xOffset, int width,int anchorWidth,
|
||||
int drawingLocationX, int screenLocationX, int displayFrameLeft,int displayFrameRight, bool allowResize);
|
||||
bool positionInDisplayHorizontal(WindowManager::LayoutParams* outParams, int width,int drawingLocationX,
|
||||
int screenLocationX, int displayFrameLeft, int displayFrameRight, bool canResize);
|
||||
void dismissImmediate(View* decorView, ViewGroup* contentHolder, View* contentView);
|
||||
void alignToAnchor();
|
||||
protected:
|
||||
void setShowing(bool);
|
||||
void setDropDown(bool isDropDown);
|
||||
@ -109,16 +125,22 @@ protected:
|
||||
bool hasContentView()const;
|
||||
bool hasDecorView()const;
|
||||
void detachFromAnchor();
|
||||
WindowManager::LayoutParams* getDecorViewLayoutParams();
|
||||
WindowManager::LayoutParams createPopupLayoutParams(long token);
|
||||
void attachToAnchor(View* anchor, int xoff, int yoff, int gravity);
|
||||
|
||||
bool isLayoutInScreenEnabled()const;
|
||||
void preparePopup(LayoutParams*p);
|
||||
void preparePopup(WindowManager::LayoutParams*p);
|
||||
PopupBackgroundView*createBackgroundView(View* contentView);
|
||||
void update(View* anchor,LayoutParams* params);
|
||||
void update(View* anchor,WindowManager::LayoutParams* params);
|
||||
bool findDropDownPosition(View* anchor,WindowManager::LayoutParams* outParams,
|
||||
int xOffset, int yOffset, int width, int height, int gravity, bool allowScroll);
|
||||
Rect getTransitionEpicenter();
|
||||
public:
|
||||
PopupWindow(Context* context,const AttributeSet& attrs);
|
||||
PopupWindow(View* contentView, int width, int height,bool focusable=false);
|
||||
PopupWindow(int width, int height);
|
||||
virtual ~PopupWindow();
|
||||
void setEpicenterBounds(const Rect& bounds);
|
||||
Drawable* getBackground();
|
||||
void setBackgroundDrawable(Drawable* background);
|
||||
@ -131,11 +153,22 @@ public:
|
||||
void setFocusable(bool focusable);
|
||||
bool isOutsideTouchable()const;
|
||||
void setOutsideTouchable(bool);
|
||||
bool isClippingEnabled();
|
||||
void setClippingEnabled(bool enabled);
|
||||
bool isClippedToScreen();
|
||||
void setIsClippedToScreen(bool enabled);
|
||||
bool isSplitTouchEnabled();
|
||||
void setSplitTouchEnabled(bool enabled);
|
||||
bool isLaidOutInScreen();
|
||||
void setIsLaidOutInScreen(bool enabled);
|
||||
void setLayoutInScreenEnabled(bool);
|
||||
bool isAttachedInDecor()const;
|
||||
void setAttachedInDecor(bool);
|
||||
void setLayoutInsetDecor(bool enabled);
|
||||
bool isLayoutInsetDecor()const;
|
||||
void setWindowLayoutType(int layoutType);
|
||||
int getWindowLayoutType();
|
||||
bool isTouchModal();
|
||||
void setTouchModal(bool touchModal);
|
||||
bool getOverlapAnchor()const;
|
||||
void setOverlapAnchor(bool overlapAnchor);
|
||||
@ -156,7 +189,7 @@ public:
|
||||
void setOnDismissListener(OnDismissListener onDismissListener);
|
||||
void update();
|
||||
void update(int width, int height);
|
||||
void update(int x, int y, int width, int height);
|
||||
void update(int x, int y, int width, int height,bool force=false);
|
||||
};
|
||||
}
|
||||
#endif//__POPUP_WINDOW_H__
|
||||
|
33
src/gui/widget/spinner.cc
Normal file → Executable file
33
src/gui/widget/spinner.cc
Normal file → Executable file
@ -1,6 +1,7 @@
|
||||
#include <widget/spinner.h>
|
||||
#include <widget/measurespec.h>
|
||||
#include <widget/listview.h>
|
||||
#include <app/alertdialog.h>
|
||||
#include <cdtypes.h>
|
||||
#include <cdlog.h>
|
||||
#define MAX_ITEMS_MEASURED 15
|
||||
@ -11,7 +12,7 @@ namespace cdroid{
|
||||
DECLARE_WIDGET2(Spinner,"cdroid:attr/spinnerStyle")
|
||||
|
||||
Spinner::Spinner(int w,int h,int mode):AbsSpinner(w,h){
|
||||
mPopupContext=nullptr;
|
||||
mPopupContext=mContext;
|
||||
mGravity= Gravity::CENTER;
|
||||
mDisableChildrenWhenDisabled=true;
|
||||
mPopup=new DialogPopup(this);
|
||||
@ -57,10 +58,10 @@ int Spinner::getDropDownHorizontalOffset() {
|
||||
}
|
||||
|
||||
void Spinner::setDropDownWidth(int pixels) {
|
||||
/*if (dynamic_cast<DropdownPopup*>(mPopup)) {
|
||||
if (dynamic_cast<DropdownPopup*>(mPopup)) {
|
||||
LOGE("Cannot set dropdown width for MODE_DIALOG, ignoring");
|
||||
return;
|
||||
}*/
|
||||
}
|
||||
mDropDownWidth = pixels;
|
||||
}
|
||||
|
||||
@ -95,7 +96,7 @@ int Spinner::getGravity()const{
|
||||
|
||||
void Spinner::onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
AbsSpinner::onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
if (mPopup != nullptr && MeasureSpec::getMode(widthMeasureSpec) == MeasureSpec::AT_MOST) {
|
||||
if (mPopup && MeasureSpec::getMode(widthMeasureSpec) == MeasureSpec::AT_MOST) {
|
||||
int measuredWidth = getMeasuredWidth();
|
||||
setMeasuredDimension(std::min(std::max(measuredWidth,
|
||||
measureContentWidth(getAdapter(), getBackground())),
|
||||
@ -450,15 +451,32 @@ Spinner::DialogPopup::DialogPopup(Spinner*spinner){
|
||||
}
|
||||
|
||||
void Spinner::DialogPopup::setAdapter(Adapter*adapter){
|
||||
mAdapter=adapter;
|
||||
mListAdapter=adapter;
|
||||
}
|
||||
|
||||
void Spinner::DialogPopup::show(int textDirection, int textAlignment){
|
||||
if (mListAdapter == nullptr) {
|
||||
return;
|
||||
}
|
||||
mPopup =AlertDialog::Builder(mSpinner->getPopupContext())
|
||||
.setTitle(mPrompt)
|
||||
.setSingleChoiceItems(mListAdapter,mSpinner->getSelectedItemPosition(),[this](DialogInterface& dialog,int which){
|
||||
LOGD("Selection=%d",which);
|
||||
mSpinner->setSelection(which);
|
||||
/*if (mSpinner->mOnItemClickListener != nullptr) {
|
||||
mSpinner->performItemClick(mSpinner, which, mListAdapter->getItemId(which));
|
||||
}*/
|
||||
dismiss();
|
||||
}).show();
|
||||
|
||||
ListView* listView = mPopup->getListView();
|
||||
listView->setTextDirection(textDirection);
|
||||
listView->setTextAlignment(textAlignment);
|
||||
}
|
||||
|
||||
void Spinner::DialogPopup::dismiss(){
|
||||
mPopup->dismiss();
|
||||
mPopup=nullptr;
|
||||
mPopup = nullptr;
|
||||
}
|
||||
|
||||
bool Spinner::DialogPopup::isShowing(){
|
||||
@ -478,6 +496,7 @@ int Spinner::DialogPopup::getVerticalOffset(){
|
||||
}
|
||||
|
||||
void Spinner::DialogPopup::setVerticalOffset(int px){
|
||||
LOGE("Cannot set vertical offset for MODE_DIALOG, ignoring");
|
||||
}
|
||||
|
||||
int Spinner::DialogPopup::getHorizontalOffset(){
|
||||
@ -485,9 +504,11 @@ int Spinner::DialogPopup::getHorizontalOffset(){
|
||||
}
|
||||
|
||||
void Spinner::DialogPopup::setHorizontalOffset(int px){
|
||||
LOGE("Cannot set horizontal offset for MODE_DIALOG, ignoring");
|
||||
}
|
||||
|
||||
void Spinner::DialogPopup::setBackgroundDrawable(Drawable* bg){
|
||||
LOGE("Cannot set popup background for MODE_DIALOG, ignoring");
|
||||
}
|
||||
|
||||
Drawable* Spinner::DialogPopup::getBackground(){
|
||||
|
4
src/gui/widget/spinner.h
Normal file → Executable file
4
src/gui/widget/spinner.h
Normal file → Executable file
@ -34,9 +34,9 @@ private:
|
||||
|
||||
class DialogPopup:public SpinnerPopup{
|
||||
private:
|
||||
PopupWindow*mPopup;
|
||||
class AlertDialog*mPopup;
|
||||
Spinner *mSpinner;
|
||||
Adapter *mAdapter;
|
||||
Adapter *mListAdapter;
|
||||
std::string mPrompt;
|
||||
public:
|
||||
DialogPopup(Spinner*spinner);
|
||||
|
Loading…
Reference in New Issue
Block a user