Feeling

              三人行,必有我?guī)熝?/p>

             ::  :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
            185 隨筆 :: 0 文章 :: 392 評論 :: 0 Trackbacks

          #

            最近很多人問我SWT Extension 項(xiàng)目上的那個(gè)不需要的JREExample是如何做出來的。我以前也會(huì)執(zhí)著于這個(gè)問題,畢竟如果不依賴于JRE的話,就不需要為用戶準(zhǔn)備一個(gè)容量極大的安裝包,但是這種做法看似有利,實(shí)則有利有弊。

          就我所知,目前把Java程序編譯成本機(jī)可執(zhí)行程序的方法有兩種,一種是GCJ,免費(fèi)的,一種是Excelsior JET,商業(yè)的。我已經(jīng)很久沒有碰過GCJ了,因?yàn)楫?dāng)初用起來實(shí)在是非常麻煩,現(xiàn)在的版本如何,我不太清楚。我自己使用的是Excelsior JET,版本為3.7。有一點(diǎn)要注意的的是,Excelsior JET的后續(xù)版本好像已經(jīng)不支持這個(gè)功能了,3.7是我所知的最后一個(gè)版本,能支持當(dāng)前所有的Win32平臺(tái)和早期的Linux(當(dāng)前比較流行的Ubuntu不支持,因?yàn)閮?nèi)核版本過高,不過企業(yè)版Redhat沒有問題)。不過我是很久以前從0day當(dāng)下來的,由于0day倉儲(chǔ)只保留一年,故現(xiàn)在已經(jīng)找不到了,我自己的機(jī)器上也沒有安裝包了(有一次大意之下,把整個(gè)Download目錄全給刪掉了,事后悔之晚矣)。

          Excelsior JET無非就是用自己的Runtime來代替JRE,只是比JRE更加靈活,根據(jù)Java程序具體的依賴來生成對應(yīng)的Runtime。其實(shí)這個(gè)Runtime也挺大的,通常10M左右,不過比起JRE,那要小很多了。SWT Extension上的那個(gè)例子只有6M,是因?yàn)槲矣?/span>ASPack把所有的DLL文件全部壓縮過了,體積小了一半。

          就我的感覺,Excelsior JETGCJ更加靈活,也更好用,畢竟是商業(yè)版的東西,它的網(wǎng)站上曾經(jīng)有例子將Eclipse 3.0編譯成本機(jī)程序,不過我當(dāng)初照著例子試了一遍,沒有成功。Excelsior JET的編譯過程極為耗時(shí),我上大學(xué)的時(shí)候,當(dāng)時(shí)機(jī)器只有128M內(nèi)存,編譯了一天JRE也沒有完成,后來找同學(xué)借了根256的內(nèi)存,這才得以完成。

          JAVA代碼編譯成本機(jī)程序的弊端也是有的,那意味著你將無法在線升級,GCJ也許可以,但是Excelsior JET是絕對不行的,這是因?yàn)樗詈笠徊揭獙λ?/span>DLL進(jìn)行鏈接,如果更換了DLL文件,它會(huì)檢測出來并報(bào)錯(cuò)。

          各位看官如果哪位有興趣,可以自行在網(wǎng)上查找Excelsior JET3.7或其他版本。由于安裝包我自己也沒有,故無法提供下載,見諒。

          posted @ 2008-05-18 15:38 三人行,必有我?guī)熝?閱讀(6838) | 評論 (7)編輯 收藏

          在SWT Extension中,引入了Function這個(gè)類。基本上所有的Win32 JNI庫都有這個(gè)類,用來直接操縱Win32 的部分API。有了這個(gè)Class,我們不用編寫JNI,就可以實(shí)現(xiàn)某些簡單的,甚至是較復(fù)雜的Win32 API。這里我們就以EnumWindows這個(gè)API舉例,看看怎么Java來執(zhí)行這個(gè)Win32 API。
              private static final String FUNTION_ENUMWINDOWS = "EnumWindows";
              
          private static final String USER32_LIB = "user32";
              
          private static List windowsList = new ArrayList();
              
              
          public static int[] enumWindows()
              {
                  windowsList.clear();
                  Callback callback 
          = new Callback(Windows.class"enumWindowsProc"2);
                  
          int address = callback.getAddress();
                  
          if (address != 0)
                  {
                      
          try
                      {
                          Function function 
          = new Function(USER32_LIB, FUNTION_ENUMWINDOWS);
                          function.invoke_I(address, 
          0);
                          function.close();
                      } 
          catch (Exception e)
                      {
                          SWT.error(SWT.ERROR_INVALID_ARGUMENT);
                      }
                      callback.dispose();
                  }
                  
          int[] handles = new int[windowsList.size()];
                  
          for (int i = 0; i < windowsList.size(); i++)
                      handles[i] 
          = ((LONG) windowsList.get(i)).value;
                  
          return handles;
              }

              
          private static int enumWindowsProc(int hwnd, int lParam)
              {
                  windowsList.add(
          new LONG(hwnd));
                  
          return 1;
              }
          EnumWindows是用來遍歷Windows窗口的API,它需要傳入一個(gè)返回boolean值的callback的地址作為參數(shù)。實(shí)際上在C里面,一個(gè)boolean值無非就是是否非0,如果為0,則為false,不為0,則為true。我們只需要new 一個(gè)function實(shí)例,傳入這個(gè)API所在的Lib和API名字,然后執(zhí)行invoke方法就OK了,在Function里面,可以最多執(zhí)行含有4個(gè)簡單類型參數(shù)的API。

          讓我們再來看看FindWindowEx這個(gè)API,它需要傳入2個(gè)int變量和2個(gè)字符串指針,根據(jù)SWT的設(shè)計(jì),我們是可以將Java的字符串轉(zhuǎn)換為指針的,因此通過Function我們也可以實(shí)現(xiàn)這個(gè)API:
              private static final String FUNTION_FINDWINDOWEX = Extension.IsUnicode ? "FindWindowExW"
                      : 
          "FindWindowExA";
              
          private static final String USER32_LIB = "user32";
              
              
          public static int findWindowEx(int parent, int hwndChildAfter, String className,
                      String windowName)
              {
                  
          int result = 0;
                  
          int lpClassName = 0;
                  
          int lpWindowName = 0;
                  
          int hHeap = Extension.GetProcessHeap();

                  
          if (className != null)
                  {
                      TCHAR buffer 
          = new TCHAR(0, className, true);
                      
          int byteCount = buffer.length() * TCHAR.sizeof;
                      lpClassName 
          = Extension.HeapAlloc(hHeap, Extension.HEAP_ZERO_MEMORY, byteCount);
                      Extension.MoveMemory(lpClassName, buffer, byteCount);
                  }
                  
          if (windowName != null)
                  {
                      TCHAR buffer 
          = new TCHAR(0, windowName, true);
                      
          int byteCount = buffer.length() * TCHAR.sizeof;
                      lpWindowName 
          = Extension.HeapAlloc(hHeap, Extension.HEAP_ZERO_MEMORY, byteCount);
                      Extension.MoveMemory(lpWindowName, buffer, byteCount);
                  }

                  
          try
                  {
                      Function function 
          = new Function(USER32_LIB, FUNTION_FINDWINDOWEX);
                      result 
          = function.invoke_I(parent, hwndChildAfter, lpClassName, lpWindowName);
                      function.close();
                  } 
          catch (Exception e)
                  {
                      SWT.error(SWT.ERROR_INVALID_ARGUMENT);
                  }
                  
          if (lpClassName != 0) Extension.HeapFree(hHeap, 0, lpClassName);
                  
          if (lpWindowName != 0) Extension.HeapFree(hHeap, 0, lpWindowName);
                  
          return result;
              }
          其實(shí)像這種簡單參數(shù)類型的API,Win32 里還有很多,我們完全不必為其專門編寫JNI,只需使用熟悉的Java即可。雖然不是調(diào)用全部的API,但大部分常用的API都是沒有問題的,關(guān)鍵是如何靈活運(yùn)用。現(xiàn)在的大型商業(yè)RCP應(yīng)用中,其實(shí)多多少少都參和了JNI,用于提升對用戶的友好性和軟件的執(zhí)行性能,畢竟Java天生就是客戶端開發(fā)的矮子。對于JNI,我們既不能一味排斥,也不能濫用,要把握一個(gè)平衡點(diǎn),使之成為Java客戶端開發(fā)的利器。
          posted @ 2008-05-11 19:31 三人行,必有我?guī)熝?閱讀(5835) | 評論 (7)編輯 收藏

          網(wǎng)上有一篇關(guān)于JNI中文問題的文章,寫得很詳細(xì),http://www.vckbase.com/document/viewdoc/?id=1611

          我在這里主要是想說說我碰到的一些問題,并且希望能從各位老大身上獲得答案。

          因?yàn)橐恢睆氖翵ava編程,基本上沒有涉及過C++的開發(fā),最近因?yàn)殚_源項(xiàng)目SWT Extension,不得已需要用JNI來實(shí)現(xiàn)一些系統(tǒng)Native功能。但是總是需要一些Java字符串對應(yīng)C++的字符串的問題。一邊情況下我都是使用SWT的TCHAR來解決問題,少部分情況需要傳遞Java String到JNI。然而少部分的這些Case總是在某些問題下出現(xiàn)亂碼或者異常。我一直使用的是網(wǎng)上比較流行的中文編碼解決方案:
          char* jstringToNative( JNIEnv  *env, jstring jstr )
          {
            
          int length = env->GetStringLength(jstr );
            
          const jchar* jcstr = env->GetStringChars(jstr, 0 );
            
          char* rtn = (char*)malloc( length*2+1 );
            
          int size = 0;
            size 
          = WideCharToMultiByte( CP_ACP, 0, (LPCWSTR)jcstr, length, rtn,(length*2+1), NULL, NULL );
            
          if( size <= 0 )return NULL;
            env
          ->ReleaseStringChars(jstr, jcstr );
            rtn[size] 
          = 0;
            
          return rtn;
          }

          jstring nativeTojstring( JNIEnv
          * env, char* str )
          {
            jstring rtn 
          = 0;
            
          int slen = strlen(str);
            unsigned 
          short * buffer = 0;
            
          if( slen == 0 )
              rtn 
          = env->NewStringUTF( str ); 
            
          else
            {
              
          int length = MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, NULL, 0 );
              buffer 
          = (unsigned short *)malloc( length*2 + 1 );
              
          if( MultiByteToWideChar( CP_ACP, 0, (LPCSTR)str, slen, (LPWSTR)buffer, length ) >0 )
                rtn 
          = env->NewString(  (jchar*)buffer, length );
            }
            
          if( buffer )
            free( buffer );
            
          return rtn;
          }

          一般情況下,這兩個(gè)函數(shù)能夠很好的工作。但是在讀寫注冊表時(shí),如果一個(gè)key的名字或者value的名字中包含了中文,jstringToNative的解決方案是不正確的,我在網(wǎng)上查了一下其它的關(guān)于Java訪問注冊表的開源項(xiàng)目,發(fā)現(xiàn)雖然它們都對字符串進(jìn)行了處理,但依然存在著中文問題。我進(jìn)行了數(shù)次嘗試,但都沒有成功。最后到了已經(jīng)絕望的時(shí)候,用開頭我提到的那篇文章中里說的最不可能用到的方法將問題成功地解決了:
          char* jstringToNative( JNIEnv  *env, jstring jstr )
          {
            
          const char* pstr = env->GetStringUTFChars(jstr, false);
            
          int nLen = MultiByteToWideChar( CP_UTF8, 0, pstr, -1, NULL, NULL );
            LPWSTR lpwsz 
          = new WCHAR[nLen];    
            MultiByteToWideChar( CP_UTF8, 
          0, pstr, -1, lpwsz, nLen );
            
          int nLen1 = WideCharToMultiByte( CP_ACP, 0, lpwsz, nLen, NULL, NULL, NULL, NULL );    
            LPSTR lpsz 
          = new CHAR[nLen1];
            
          int size = 0;
            size 
          = WideCharToMultiByte( CP_ACP, 0, lpwsz, nLen, lpsz, nLen1, NULL, NULL );
            
          if( size <= 0 ){
                delete [] lpwsz;
                
          return NULL;
            }
            env
          ->ReleaseStringUTFChars(jstr, pstr );
            delete [] lpwsz;
            
          return lpsz;
          }
          問題雖然解決了,但是我卻不求甚解,為什么直接通過env拿到unicode字串,然后轉(zhuǎn)成多字節(jié)串不行,但是通過env拿到utf-8字串,然后轉(zhuǎn)成unicode字串,再將這個(gè)unicode字串轉(zhuǎn)成多字節(jié)串就能工作?

          如果大家有興趣的話,不妨試試,用JNI調(diào)用RegOpenKeyEx這個(gè)API,就能驗(yàn)證我說的這個(gè)Case。哪位老大對JNI比較在行的話,可以在評論中告訴我,不甚感激。
          posted @ 2008-05-04 13:17 三人行,必有我?guī)熝?閱讀(4032) | 評論 (2)編輯 收藏

          Glossy 效果,顧名思義,就是玻璃質(zhì)的光澤透明的效果,在Windows平臺(tái)下的應(yīng)用越來越廣泛,從Media Player10開始,它的button已經(jīng)運(yùn)用上了此效果。現(xiàn)在但凡是微軟新發(fā)布的軟件,十有八九都帶有g(shù)lossy特效。Glossy 效果使用了Gdi Plus的API,因此在Win98和Win2000下,必須安裝gdiplus.dll才能使用,此動(dòng)態(tài)鏈接庫不大,只有700多K,但是想要在自己的應(yīng)用程序中畫出絢麗多彩的效果,那是少不了這個(gè)小東西的。關(guān)于Glossy效果的描述,可以參見CodeProject上的一片文章WindowsVistaRenderer,http://www.codeproject.com/KB/vista/WindowsVistaRenderer.aspx

          Glossy特效有一個(gè)重要的組成部分,就是橢圓的光暈,此效果在Linux下可能并沒有實(shí)現(xiàn)(并未下定論,我還沒有深入研究過Linux下的圖形庫), 所以SWT的Gdip并沒有將其公開出來,而是放入custom的API里,也就是說,你可以自行調(diào)用此效果的API,但是SWT并不負(fù)責(zé)為你提供封裝, 因此你并不能使用GC來實(shí)現(xiàn)該特效,這對我們的界面開發(fā)極為不利,自己調(diào)用Gdip的API,繁瑣不說,還很容易導(dǎo)致JVM退出。

          為了能夠方便的使用GC來畫出此特效,我們不得不采用一些非常規(guī)的手段:反射。利用反射我們可以拿到GC的一些內(nèi)部數(shù)據(jù),在這個(gè)地方,我們只需要拿到GCData就可以,它包含了畫圖所需要具備的元素。Glossy效果需要使用PathGradientBrush,我們把這個(gè)刷子賦給GCData,就可以使用GC來畫出glossy特效了。
           1 public class GCExtension {
           2 
           3     private GC gc;
           4 
           5     private GCData data;
           6 
           7     public GCExtension(GC gc) {
           8         this.gc = gc;
           9         data = getGCData(gc);
          10     }
          11 
          12     public void fillGradientPath(Path path, float[] centerPoint,
          13             Color centerColor, int centerColorAlpha, Color[] surroundColors,
          14             int[] surroundColorAlphas) {
          15         if (gc == null || gc.handle == 0)
          16             SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
          17         if (path == null || centerPoint == null || centerColor == null
          18                 || surroundColorAlphas == null)
          19             SWT.error(SWT.ERROR_NULL_ARGUMENT);
          20         if (path.handle == 0 || centerPoint.length < 2
          21                 || centerColor.handle == 0
          22                 || surroundColors.length != surroundColorAlphas.length)
          23             SWT.error(SWT.ERROR_INVALID_ARGUMENT);
          24         for (int i = 0; i < surroundColors.length; i++) {
          25             if (surroundColors[i] == null || surroundColors[i].handle == 0)
          26                 SWT.error(SWT.ERROR_INVALID_ARGUMENT);
          27         }
          28 
          29         int brush = Gdip.PathGradientBrush_new(path.handle);
          30         if (brush == 0)
          31             SWT.error(SWT.ERROR_NO_HANDLES);
          32         PointF point = new PointF();
          33         point.X = centerPoint[0];
          34         point.Y = centerPoint[1];
          35         Gdip.PathGradientBrush_SetCenterPoint(brush, point);
          36 
          37         int colorRef = centerColor.handle;
          38         int rgb = ((colorRef >> 16& 0xFF| (colorRef & 0xFF00)
          39                 | ((colorRef & 0xFF<< 16);
          40         int color = Gdip.Color_new(centerColorAlpha << 24 | rgb);
          41         if (color == 0)
          42             SWT.error(SWT.ERROR_NO_HANDLES);
          43         Gdip.PathGradientBrush_SetCenterColor(brush, color);
          44         Gdip.Color_delete(color);
          45 
          46         int[] colors = new int[surroundColors.length];
          47         for (int i = 0; i < surroundColors.length; i++) {
          48             colorRef = surroundColors[i].handle;
          49             rgb = ((colorRef >> 16& 0xFF| (colorRef & 0xFF00)
          50                     | ((colorRef & 0xFF<< 16);
          51             colors[i] = Gdip.Color_new(surroundColorAlphas[i] << 24 | rgb);
          52             if (colors[i] == 0)
          53                 SWT.error(SWT.ERROR_NO_HANDLES);
          54         }
          55         Gdip.PathGradientBrush_SetSurroundColors(brush, colors,
          56                 new int[] { colors.length });
          57         for (int i = 0; i < surroundColors.length; i++) {
          58             Gdip.Color_delete(colors[i]);
          59         }
          60         data.gdipBrush = brush;
          61         boolean advanced = gc.getAdvanced();
          62         if (!advanced)
          63             gc.setAdvanced(true);
          64         int mode = Extension.GetPolyFillMode(gc.handle) == Extension.WINDING ? Gdip.FillModeWinding
          65                 : Gdip.FillModeAlternate;
          66         Gdip.GraphicsPath_SetFillMode(path.handle, mode);
          67         Gdip.Graphics_FillPath(data.gdipGraphics, data.gdipBrush, path.handle);
          68         if (!advanced)
          69             gc.setAdvanced(false);
          70         if (data.gdipBrush != 0) {
          71             Gdip.PathGradientBrush_delete(data.gdipBrush);
          72             data.gdipBrush = 0;
          73         }
          74     }
          75 
          76     private GCData getGCData(GC gc) {
          77         GCData data = null;
          78         try {
          79             Object obj = null;
          80             Field field = gc.getClass().getDeclaredField("data");
          81             if (field != null) {
          82                 field.setAccessible(true);
          83                 obj = field.get(gc);
          84             }
          85             if (obj != null && obj instanceof GCData)
          86                 data = (GCData) obj;
          87         } catch (Exception e) {
          88 
          89         }
          90         return data;
          91     }
          92 }

          特效截圖:

          posted @ 2008-04-30 15:54 三人行,必有我?guī)熝?閱讀(3550) | 評論 (3)編輯 收藏

          SWT Win32 Extension寫到現(xiàn)在的狀況,在win32 natvie上面已經(jīng)沒有太多花樣了,常用的一些功能我都已經(jīng)做得差不多了,現(xiàn)在主要是做一些自定義的控件,就目前的進(jìn)度,還只是完成了Shell,Menu,ToolBar 3個(gè)部分,還有很多內(nèi)容可以慢慢完善。不過自從發(fā)布了自定義的菜單以后,SWT Win32 Extension的用戶群大增,也對我提出了更高的要求。不過現(xiàn)在的主要任務(wù)是實(shí)現(xiàn)功能,因此代碼的質(zhì)量上肯定是差了點(diǎn)。現(xiàn)有的接口都是我自己通過Example的需求來加的,以后等功能做的完善上,再將現(xiàn)有的架構(gòu)進(jìn)行較大的重構(gòu),我想應(yīng)該是一個(gè)不錯(cuò)的步驟。畢竟就我一個(gè)人做這個(gè)東西,還要兼職寫Example,Document,測試,網(wǎng)站維護(hù),雖然每天都在加班加點(diǎn),但還是感覺時(shí)間不夠用。每天都有用戶發(fā)郵件來催進(jìn)度,所以維護(hù)這個(gè)項(xiàng)目現(xiàn)在真的是讓我廢寢忘食了,但總體來說還是物有所值,畢竟辛辛苦苦的努力,還是有所回報(bào)的。開源嘛,本來就是一種奉獻(xiàn)精神,回饋社會(huì),讓所有人都來分享自己的成果。

          這些天一直忙著寫新的Feature,今天寫的差不多了,于是回過頭來整理Example。本來上個(gè)版本我就想接管Eclipse Native的菜單,不過沒能如愿,因?yàn)镋clipse的菜單都是LazyLoad的。今天又嘗試了一下,終于成功的實(shí)現(xiàn)了這個(gè)功能。做完了才知道其實(shí)很簡單,所遇到的重重障礙只不過是因?yàn)樽约旱目蚣芾鲜潜某鲂碌腷ug。唉,自己測試自己開發(fā)的東西總是有盲點(diǎn)存在,實(shí)在是無能為力呀。

          從本質(zhì)上來說,我自定義的菜單和標(biāo)準(zhǔn)菜單控件的代碼及事件上的實(shí)現(xiàn)基本一致,所以接管Eclipse原生的菜單并不是一件很難的事情,當(dāng)自定義的菜單接收到一個(gè)事件的時(shí)候,只需將這個(gè)事件轉(zhuǎn)發(fā)給Eclipse的原生菜單就好了,一切就是這么簡單。重點(diǎn)就是Notify SWT.Selected 和 SWT.Show 事件,前者用來觸發(fā)Action的行為,后者用來觸發(fā)Eclipse原生菜單的LazyLoad。

          截圖如下:
          posted @ 2008-04-20 20:37 三人行,必有我?guī)熝?閱讀(3390) | 評論 (4)編輯 收藏


          The idea is from DotnetMagic, I copied its style, but different implement methods. DotnetMagic uses shell self message circulation, but I use swt event listener. I want to implement the custom style menu for all platforms initially, but it's impossible. It has to use a lot of advanced OS funcitions. If I use pure swt public functions, I can't implement  some features. For example, if I click the menu, the window shell will be deactivated, I click window shell's titlebar, swt event manager doesn't send messages to me. I must use WND Message hook to deal these messages. So I have to add the feature into SWT Win32 Extension, but not a independent project.

          Some beautiful snapshots:


          Office 2003 Style Menu


          VS 2005 Style Menu


          Project Download: http://www.swtui.cn/downloads/org.eclipse.swt.win32.extension.zip
          JNLP Online Demo: http://www.swtui.cn/jws/example.jnlp

          If you don't have installed Java Runtime, you can access it via http://www.swtui.cn/downloads/org.eclipse.swt.win32.extension.example.independence_native.zip

          Eclipse Plugin Update Site URL: http://www.swtui.cn/update

           

          posted @ 2008-04-02 11:25 三人行,必有我?guī)熝?閱讀(3137) | 評論 (5)編輯 收藏

          Add Flash Control to SWT Win32 Extension, now you can check out the latest code from CVS and run it.

          Project Main Page: http://www.swtui.cn

          cvs -d:pserver:anonymous@feeling.cvs.sourceforge.net:/cvsroot/feeling login



          Flash Control Listener   


          Flash Control Hook Interceptor

           

          posted @ 2008-03-14 22:00 三人行,必有我?guī)熝?閱讀(2658) | 評論 (0)編輯 收藏

          在SWT Win32 Extension 中新添加了窗口系統(tǒng)菜單管理功能,現(xiàn)在可以自定義窗口系統(tǒng)菜單了。
          posted @ 2008-03-10 20:38 三人行,必有我?guī)熝?閱讀(2272) | 評論 (0)編輯 收藏

          窗口是一個(gè)應(yīng)用程序的門面,有一個(gè)好看的窗口,用戶的評價(jià)自然也會(huì)大大提高,經(jīng)過幾天的努力,終于在SWT Win32 Extension中加入了自定義的Window Theme,當(dāng)然目前只完成了一些基本的實(shí)現(xiàn),高級實(shí)現(xiàn)依然有待于研究。


          Windows XP Theme


          Custom Theme

            目前已完成了任意SWT Shell wrapper,系統(tǒng)菜單管理,不規(guī)則邊框的切邊等功能,尚未完成的功能還有很多,比如窗口菜單。未來準(zhǔn)備加入用戶自定義Theme的接口,只要符合規(guī)范都可以進(jìn)行自動(dòng)切換。由于功能仍然還有很多地方尚未完成,暫時(shí)還沒有提供打包下載,有興趣的話,可以從項(xiàng)目CVS上Checkout出來看看效果。

          cvs -d:pserver:anonymous@feeling.cvs.sourceforge.net:/cvsroot/feeling login
          posted @ 2008-01-15 14:25 三人行,必有我?guī)熝?閱讀(2819) | 評論 (0)編輯 收藏

          做Java UI的人應(yīng)該都很熟悉Look and Feel,Swing擁有的這個(gè)功能的確是相對于SWT的一個(gè)巨大優(yōu)勢。不過SWT的GC也可以畫出自己的UI,前提是這個(gè)控件是Custom的,而不是系統(tǒng)級的。Eclipse Presentation 就是對eclipse本身UI提供的一個(gè)擴(kuò)展。本來我還對這個(gè)擴(kuò)展很友好的,不過現(xiàn)在覺得真是一鍋粥里掉了個(gè)老鼠屎,完全變了味道。

          由于閑來無視,把一個(gè)1年半前一個(gè)德國人寫的Eclipse VS L&F Plugin down了下來,無奈bug太多,用戶體驗(yàn)也和我個(gè)人感覺不一致,索性就把代碼check out 出來,作了一些本地修改。不過讓我吐血的地方就是,如果我從eclipse default L&F 切換到這個(gè)L&F,就問題一堆,從其它的L&F切換就沒有問題。Debug了半天,毫無進(jìn)展,只是發(fā)現(xiàn)很多地方都是Null Exception。于是把Eclipse 2.2 L&F的代碼翻了出來,經(jīng)過仔細(xì)對照,還是沒有找到解決的方案,我就感覺怪怪的,也不知道哪兒出了問題,覺得大概是自己沒有把Presentation的代碼吃透的原因。于是又回頭開始一行行的從有問題的代碼處開始Debug,看看我的代碼和2.2L&F的代碼在運(yùn)行時(shí)到底有什么區(qū)別,終于功夫不負(fù)有心人,我發(fā)現(xiàn)這個(gè)代碼片斷:
              /**
               * Sets the minimized state for this stack. The part may call this method to
               * minimize or restore itself. The minimized state only affects the view
               * when unzoomed.
               *
               * This implementation is specific to the 3.3 presentation's
               * min/max story; otherwise it just forwards the call.
               
          */

              
          public void setMinimized(boolean minimized) {
                  
          // 'Smart' minimize; move the stack to the trim

                  Perspective persp = getPage().getActivePerspective();
                  
          if (Perspective.useNewMinMax(persp)) 
          {
          原來3.3的L&F做了專門處理,而我的代碼和3.3是一致的,和 2.2L&F是不一致的,不過我找了半天,也沒有在2.2L&F的代碼里找出異樣之處,暈的不行。唯一的線索就是
          boolean useNewMinMax = preferenceStore.getBoolean(IWorkbenchPreferenceConstants.ENABLE_NEW_MIN_MAX);

          可惡的是,IWorkbenchPreferenceConstants.ENABLE_NEW_MIN_MAX 這個(gè)靜態(tài)常量是無法在項(xiàng)目里找到eclipse自身的引用。2.2L&F plugin里也沒有,該死的eclipse肯定是寫死在代碼里了。于是翻出editplus,對eclipse ui workbench的代碼多文件搜索了一把,然后開始吐血,它居然把所有的L&F的配置都寫在UI Workbench的Preference Page里,這還算什么插件,根本就沒有把擴(kuò)展的接口給出來,還是很重要的一個(gè)配置。其實(shí)2.2L&F以前只是它的一個(gè)內(nèi)部package,后來重構(gòu)成一個(gè)plugin,3.0L&F到現(xiàn)在依然還是一個(gè)package。不過我想既然2.2L&F做成插件了,怎么也改和系統(tǒng)獨(dú)立開來呀,現(xiàn)在這樣就成了一個(gè)半吊子的plugin.

          Eclipse終于被我bs了一把^_^,林子大了,什么鳥都有。


          改過之后L&F自己覺得好用了不少

           

          posted @ 2007-12-25 19:19 三人行,必有我?guī)熝?閱讀(3562) | 評論 (5)編輯 收藏

          僅列出標(biāo)題
          共9頁: 上一頁 1 2 3 4 5 6 7 8 9 下一頁 
          GitHub |  開源中國社區(qū) |  maven倉庫 |  文件格式轉(zhuǎn)換 
          主站蜘蛛池模板: 南丰县| 铜梁县| 龙里县| 松潘县| 彭阳县| 阿勒泰市| 舒城县| 临西县| 晋江市| 高密市| 左贡县| 大关县| 巩留县| 鄯善县| 富蕴县| 松潘县| 龙海市| 宜兴市| 屏东县| 盐边县| 蓬莱市| 古交市| 南涧| 清远市| 张北县| 达日县| 禹城市| 汉阴县| 铁力市| 贵定县| 林西县| 栾川县| 大足县| 台中市| 桓台县| 嘉义县| 扎赉特旗| 沂水县| 桐庐县| 开化县| 建德市|