OS X 10.5以降のフルスクリーン実装サンプル
[]

2011.08.14

このエントリーをはてなブックマークに追加
はてなブックマーク - OS X 10.5以降のフルスクリーン実装サンプル

OS X 10.5から追加された NSView の enterFullScreenMode:withOptions:、exitFullScreenModeWithOptions:を使ったフルスクリーンの実装サンプル。

環境

  • OS X 10.6.7
  • Xcode 4.0.2
  • ビルドターゲットのバージョンは10.5以降が必須。

1. 新規プロジェクト作成

  • Cocoa アプリケーションのプロジェクトテンプレートで新規プロジェクトを作成。

2. AppControllerクラスファイルの作成

  • AppController.h
  • AppController.m

3. MainViewクラスファイルの作成

  • MainView.h
  • MainView.m

4. IBでMainViewの配置と設定

  • XcodeのNavigator AreaからMainMenu.xibをクリックしてUI編集画面を表示する。
  • Object Libraryから「Object」をXcode の 「Dock」にドラッグアンドドロップ。
  • 配置したObjectをクリックして、インスペクタペインの「Custome Class」にMainViewと入力する。

5. IBでAppControllerの設定

  • XcodeのNavigator AreaからMainMenu.xibをクリックしてUI編集画面を表示する。
  • Object Libraryから「Object」をXcode の 「Dock」にドラッグアンドドロップ。
  • 配置したObjectをクリックして、インスペクタペインの「Custome Class」にAppControllerと入力する。
  • 「Assistant Editor ボタン」をクリックして、AppController.h に MainView をアウトレットとして接続する。

6. IBで「Full Screen」メニューアイテムの追加

  • XcodeのNavigator AreaからMainMenu.xibをクリックしてUI編集画面を表示する。
  • Object Libraryから「Menu Item」をメニュー「View」以下(別にどこでもよいけど)に配置する。
  • 配置した「Menu Item」を選択し、インスペクタペインの「Title」に「Full Screen」、「Key Equivalant」には「Cmd + F」を設定する。
  • 「Assistant Editor ボタン」をクリックして、AppController.h に向けて「Menu Item」からCtrl + クリックでアクションを接続する。アクション名はとりあえず「fullscreen」とする。

※ 「Cmd + F」は既に他のメニューアイテムによって使われているので、とりあえず、「View」以外のメニューは削除しておくか、フルスクリーンのキーボードショートカットを「Cmd + F」以外にする必要がある。

7. MainViewクラスの実装

  • MainView.h
#import <Foundation/Foundation.h>

@interface MainView : NSView
{}
@end
  • MainView.m
#import "MainView.h"

@implementation MainView
@end

8. AppControllerクラスの実装

  • AppController.h
#import <Foundation/Foundation.h>

@class MainView;

@interface AppController : NSObject
{
    IBOutlet MainView *mainView;
}
- (IBAction)fullscreen:(id)sender;
@end
  • AppController.m
#import "AppController.h"

@implementation AppController

#pragma - menu

- (IBAction)fullscreen:(id)sender
{
    NSLog(@"isInFullScreenMode: %i", [mainView isInFullScreenMode]);
    NSDictionary *fullscreenOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:NSFullScreenModeSetting];
   
    if([mainView isInFullScreenMode]){
        [mainView exitFullScreenModeWithOptions:fullscreenOptions];
    }
    else{
        [mainView enterFullScreenMode:[NSScreen mainScreen] withOptions:fullscreenOptions];
    }
   
    // mainViewをFirst Responderにすることで、フルスクリーン表示後にキーボードイベントを受け取れるようにする。
    // でないと、ショートカットキー(Cmd + F)でフルスクリーンを解除できなくなる。
    [[mainView window] makeFirstResponder:(NSResponder *)mainView];
}
@end

ソース

その他

Flex + actionscript3 でスライドショー
[]

2011.07.29

このエントリーをはてなブックマークに追加
はてなブックマーク - Flex + actionscript3 でスライドショー

スライドショーの作例。

開発環境

  • OS X 10.6.2
  • flex_sdk_4.1.0.16076
  • rascut 0.2.1

rascutを使っての環境構築の記事:http://d.hatena.ne.jp/nitoyon/20070914/how_to_install_rascut

key points

  • そうめん(擬似thread)を使わせてもらいました。
  • Tweener
  • XMLで動きを定義しています。

デモ

ソース

ドラッグアンドドロップで
ファイルアップロードできるサービス

[]

2011.05.09

このエントリーをはてなブックマークに追加
はてなブックマーク - ドラッグアンドドロップで<br />ファイルアップロードできるサービス

を作ってみました。Safari、Firefox、Chromeだとたぶん動く、IEだと動かない。

screen shot:

主な構成要素

  • CodeIgniter 2.0
  • Doctrine
  • MySQL
  • Flash
  • jQuery

CodeIgniter 2.0 の新機能、変更点など
[]

2011.02.05

このエントリーをはてなブックマークに追加
はてなブックマーク - CodeIgniter 2.0 の新機能、変更点など

CodeIgniter 2.0 のブランチ

  • http://d.hatena.ne.jp/Kenji_s/20110129/1296265837
  • CodeIgniter Core
    • CIの開発元であるEllisLab の商用製品( Such as ExpressionEngine and MojoMotor )で使用されるブランチ
  • CodeIgniter Reactor
    • これがオープンソースコミュニティのためのメインブランチ。
    • CI コミュニティで育てていくためのブランチ。
    • 新機能、バグフィックス、改良、ドキュメンテーションの整備はこちらで行なわれる。
    • EllisLabによる CodeIgniter Core の成果物もこちらにマージされていく。

大きな変更点、新機能

  • PHP 4 サポートの廃止。今後は PHP 5.1 以上が必須要件となる。
  • フォームヘルパーでのCSRFプロテクション
  • Drivers
    • CodeIgniter 2.0 In Progress – The Critical Changes, Implications, and What You Should Know
    • Guide to CodeIgniter Drivers
    • ドライバーとはライブラリーの一種。
    • コントローラにライブラリ使用のためのエレガントなシンタックスを提供する。
    • adapter パターン + decorator パターン
    • Caching
      • $this->load->driver('cache');
      • $this->cache->memcached->save('foo', 'bar', 10);
      • $this->cache->apc->save('foo', 'bar', 10);
      • Cache_memcachedクラスからその親クラスであるCacheクラスにアクセスすることはできるが、
      • Cache_memcachedからCache_apcにアクセスするこはできない => クラスの機能を明確に分離する。
    • Database
    • Javascript
  • Application Packages
    • コンフィグファイル、ヘルパー、言語ファイル、ライブラリ、モデルといった アプリケーションに必要なコードを単一ディレクトリで構成することができる機能。プラグインのような感じで配布することが容易になる。
    • $this->load->add_package_path(APPPATH.'third_party/foo_bar/');
    • $this->load->library('foo_bar');
    • http://codeigniter.com/user_guide/libraries/loader.html
  • Scaffoldingの廃止。
  • Validationクラスは削除されました。=> Form Validationクラスを使う。
  • 今までのPlugin機能の削除。ヘルパーを使ってね。
  • Added routing overrides to the main index.php file, enabling the normal routing to be overridden on a per “index” file basis.
    • メインのindex.phpファイルを上書きするルーティングが追加されたので、通常のルーティングを有効にするには各"index"ファイルを上書きする。(よくわかんね)
  • 404ページをコントローラで制御するために$route[‘404_override’]を追加しました。
  • 50以上のバグフィックス。

Reactor には上記のものすべてに加え、以下のナイスな独自変更を含んでいる(以下のものはCoreには含まれないという意味だろう):

  • GETクエリ文字列の完全なサポート。
  • base_urlがブランクなら自動的に探知する。
  • ファイルシステムによる新しいキャッシュドライバー、APCとmemcacheのサポート
  • 簡単なcronジョブのためのコマンドラインに対応する。
  • 20以上の調整と改善。

すべての変更点はchange logをご覧あれ

コアクラスの拡張

コアクラス(system/core 内の CI_Controller など)の拡張クラス(MY_Controller)は

  • application/core

に配置する必要がある。 つまり application/libraries/MY_Controller.php は、application/core/MY_Controller.php に移動する必要がある。

system/libraries 内のクラスの拡張は 今まで通り application/libraries に配置してOK

refs

追記 2012.02.11

  • php5.3からはCIではなく、fuelPHPを使わせてもらうとこにした。
  • CIのライセンス問題ではなく単に実装の好みの問題で。

XULRunnerでページ読み込みメーターを実装する
[]

2011.01.27

このエントリーをはてなブックマークに追加
はてなブックマーク - XULRunnerでページ読み込みメーターを実装する

参考リンク

ポイント

  • (1). browser.xulに を配置する。
  • (2). nsIWebProgressListenerインターフェースを実装したオブジェクトを作成する。
  • (3). (2)で作成したオブジェクトを gBrowser.addProgressListener でgBrowserにセットする。

(1). browser.xul の一部

<!-- ... -->
    <browser type="content" flex="1" id="content"/>
<!-- ... -->
    <statusbarpanel class="statusbarpanel-progress" collapsed="true" id="statusbar-progresspanel">
         <image src="chrome://yobrowser/content/throbber.gif" id="throbber-image"/>
         <progressmeter class="progressmeter-statusbar" id="statusbar-icon" mode="normal" value="0"/>
    </statusbarpanel>
<!-- ... -->

(2)(3). MyProgressListenerの実装とセット

var gBrowser = null;
var gProgressMeterPanel = null;

function BrowserStartup()
{
  // ....
  gBrowser = document.getElementById("content");
  gProgressMeterPanel = document.getElementById("statusbar-progresspanel");
  gBrowser.addProgressListener(MyProgressListener, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
  // ....
}

var MyProgressListener = {
  , statusMeter: null    // progressmeter
  , QueryInterface: function(aIID) {
      if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
          aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
          aIID.equals(Components.interfaces.nsISupports))
            return this;
          throw Components.results.NS_NOINTERFACE;
  }
  , onProgressChange : function (aWebProgress, aRequest,
                               aCurSelfProgress, aMaxSelfProgress,
                               aCurTotalProgress, aMaxTotalProgress)
  {
    if (aMaxTotalProgress > 0) {
      var percentage = (aCurTotalProgress * 100) / aMaxTotalProgress;
      this.statusMeter.value = percentage;
    }
  }
  , onStateChange: function (aWebProgress, aRequest, aStateFlags, aStatus)
  {
    const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
    const nsIChannel = Components.interfaces.nsIChannel;

    if(aStateFlags & nsIWebProgressListener.STATE_START && aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK){
      dump("読み込み開始");
     
      var location = aRequest.QueryInterface(nsIChannel).URI;
      gProgressMeterPanel.collapsed = false;
     
      this.statusMeter = document.getElementById("statusbar-icon");
      this.statusMeter.value = 0;
    }
    else if (aStateFlags & nsIWebProgressListener.STATE_STOP && aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
      dump("読み込み終了");
      gProgressMeterPanel.collapsed = true;
    }
  }
  , onLocationChange: function (aWebProgress, aRequest, aLocationURI)
  {}
  , onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage)
  {}
  , onSecurityChange: function (aWebProgress, aRequest, aState)
  {}
}

jquery.summary.js
[]

2011.01.15

このエントリーをはてなブックマークに追加
はてなブックマーク - jquery.summary.js

指定したセレクタ内の h1...h6 からTOCを生成する。デフォルトでは <div id="summary"></div> 内に生成される。

download

ソース

;(function($){
  var namespace = "createSummary";
  $.fn[namespace] = function(config) {
    var config = $.extend({
      where:'#summary'
    }, config);
    var target = this;
    $(config.where).append('<ul></ul>');
    var ul = '<ul style="margin-left:2em;"></ul>';
    var h = $(target).find('h1, h2, h3, h4, h5, h6');
    function getN(ele)
    {
      ele.nodeName.match(/(\d)/i);
      return RegExp.$1;
    }
   
    $.each(h, function(i, v)
    {
      var n = getN(v);
      var t = 'h'+n+'-'+i;
      var li = '<li>' + '<a href="#' + t + '">' + $(v).text() + '</a>' + '</li>';
     
      $(v).append('<a name="' + t + '"></a>');
     
      if(i <= 0){
        $(config.where + " ul:last").append(li);
      }
      else{
        var p_n = getN(h[i-1]); // prev n
       
        if(n < p_n){
          $(config.where + " ul:last").parents('ul:last').append(li);
        }
        else if(n > p_n){
          $(config.where + " li:last").append(ul);
          $(config.where + " ul:last").append(li);
        }
        else{
          $(config.where + " li:last").after(li);
        }
      }
    });
  };
})(jQuery);

使い方

<html>
<head>
<script type="text/javascript">
jQuery(function($){
  // div.entry 内の見出しタグ(h1 ... h6)から div#summary 内にTOCを生成
  $("div.entry").createSummary();
});
</script>
</head>
<body>

<div id="summary"></div>

<div class="entry">
    <h1>見出し1</h1>
    <h2>見出し2</h2>
    <h3>見出し3</h3>
</div>

</body>

ボタンが押されたら画面をロックする
[]

2011.01.08

このエントリーをはてなブックマークに追加
はてなブックマーク - ボタンが押されたら画面をロックする

エンタープライズアプリだとよくあるご要望で、とにかくなんか処理を起動したら、終わるまで画面をいじれないようにしたい。

index.html

<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8" />
<title>screenlock test</title>
<script type="text/javascript" src="./jquery.js"></script>
<script type="text/javascript">
$(function() {
  $("#Btn").click(function(evt)
  {
    lockScreen();
   
    //「?time=xxxx」はIEのキャッシュ対策
    var url = './main.php?' + new Date().getTime();
   
    $.getJSON(url, function(evt)
    {
      // サーバーからレスポンスがあった
      unlockScreen();
      alert(evt[0]);
    });
  });
 
  function lockScreen()
  {
    $("body").append('<div id="LockScreen" style="position:absolute;left:0;top:0;width:100%;height:100%;color:black;background:white;opacity:0.8;filter:alpha(opacity=80);"><p align="center">現在重い処理をしてます。<br />しばらくお待ちくださいでやんす。<br /><img src="loading.gif" /></p></div>');
  }
  function unlockScreen()
  {
    $("#LockScreen").remove();
  }
});
</script>
</head>
<body>
<input type="button" name="btn" id="Btn" value="処理開始" />
</body>
</html>

main.php

<?php

// なんか重い処理
sleep(10);

// レスポンスする
$ret = array(
  '処理完了'
);
echo json_encode($ret);

設定ファイルを指定してzfコマンドを実行する
[]

2010.12.15

このエントリーをはてなブックマークに追加
はてなブックマーク - 設定ファイルを指定してzfコマンドを実行する

$ export ZF_CONFIG_FILE=./.zf.ini
$ php scripts/zf show config
User Configuration: ./.zf.ini
  |-- php
  |   `-- include_path: /Users/yokada/work/web/49283/site/pragma/libs:.
  |-- basicloader
  |   `-- classes
  |       |-- 1: Pragma_Tool_Provider_Hello
  |       `-- 2: Pragma_Tool_Provider_Doctrine
  `-- basePath: /Users/yokada/work/web/49283/site

または、一行で、

$ ZF_CONFIG_FILE=./.zf.ini zf show config

指定した設定ファイルが無ければ、HOMEディレクトリ(ZF_HOME、HOME、HOMEPATH、USERPROFILE)の環境変数のパスにある .zf.ini が読み込まれる。

ブートストラップでリクエストを初期化する
[]

2010.12.14

このエントリーをはてなブックマークに追加
はてなブックマーク - ブートストラップでリクエストを初期化する

デフォルトではリクエストオブジェクトはFrontControllerによるディスパッチループの本体であるdispatchメソッドで初期化されるが、ブートストラップでリクエストオブジェクトを利用して、URLごとに処理を振り分けたい場合に。

モジュールを使わない場合

application/Bootstrap.php でリクエストオブジェクトを初期化する

<?php

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
  protected function _initRequest()
  {
    $request = new Zend_Controller_Request_Http();
    Zend_Controller_Front::getInstance()->getRouter()->route($request);
    var_dump($request);
    /**
     * /a/b/c をリクエストした場合
     *
    object(Zend_Controller_Request_Http)[10]
      protected '_paramSources' =>
      array
        0 => string '_GET' (length=4)
        1 => string '_POST' (length=5)
      protected '_requestUri' => string '/a/b/c' (length=6)
      protected '_baseUrl' => string '' (length=0)
      protected '_basePath' => null
      protected '_pathInfo' => string '/a/b/c' (length=6)
      protected '_params' =>
      array
        'controller' => string 'a' (length=1)
        'action' => string 'b' (length=1)
        'module' => string 'default' (length=7)
      protected '_rawBody' => null
      protected '_aliases' =>
      array
        empty
      protected '_dispatched' => boolean false
      protected '_module' => string 'default' (length=7)
      protected '_moduleKey' => string 'module' (length=6)
      protected '_controller' => string 'a' (length=1)
      protected '_controllerKey' => string 'controller' (length=10)
      protected '_action' => string 'b' (length=1)
      protected '_actionKey' => string 'action' (length=6)
    */

  }
}

モジュールを使う場合(Aというモジュールを例とする)

application/modules/a/Bootstrap.php でリクエストオブジェクトを初期化する。

<?php

class A_Bootstrap extends Zend_Application_Module_Bootstrap
{
  protected function _initModuleRequest()
  {
    $request = new Zend_Controller_Request_Http();
    Zend_Controller_Front::getInstance()->getRouter()->route($request);
    var_dump($request);
    /**
     * /a/b/cをリクエストした場合
     *
    object(Zend_Controller_Request_Http)[31]
      protected '_paramSources' =>
      array
        0 => string '_GET' (length=4)
        1 => string '_POST' (length=5)
      protected '_requestUri' => string '/a/b/c' (length=6)
      protected '_baseUrl' => string '' (length=0)
      protected '_basePath' => null
      protected '_pathInfo' => string '/a/b/c' (length=6)
      protected '_params' =>
      array
        'module' => string 'a' (length=1)
        'controller' => string 'b' (length=1)
        'action' => string 'c' (length=1)
      protected '_rawBody' => null
      protected '_aliases' =>
      array
        empty
      protected '_dispatched' => boolean false
      protected '_module' => string 'a' (length=1)
      protected '_moduleKey' => string 'module' (length=6)
      protected '_controller' => string 'b' (length=1)
      protected '_controllerKey' => string 'controller' (length=10)
      protected '_action' => string 'c' (length=1)
      protected '_actionKey' => string 'action' (length=6)
     */

  }
}

モジュールを使う場合は、実際は自分用のモジュールブートストラップ(MyModuleBootstrap extends Zend_Application_Module_Bootstrap) を作成して、そこに初期化処理を書くことになると思う。

lsof コマンド
[]

2010.12.03

このエントリーをはてなブックマークに追加
はてなブックマーク - lsof コマンド

OS X でも lsof コマンドを使用することができる。このコマンドはアプリケーションが使用しているファイルを一覧することができ、ファイルがネットワーク越しに存在する場合は接続情報付きで見ることができる。

まず netstat でポートの使用状況を見る。

$ netstat a
... 略
tcp4 0 0 192.168.1.200.50930 128.242.245.39.https ESTABLISHED
... 略

自分のマシン(192.168.1.200:50930)から 128.242.245.39 に対して https で接続していることがわかる。IPやポート番号から lsof コマンドを使ってアプリケーションを特定することができる。

$ lsof | grep 128.242.245.39
YoruFukur 446 yokada 11u IPv4 0xXXXXXXXX 0t0 TCP 192.169.1.200:50930->128.242.245.39:https (ESTABLISHED)

YoruFukurou が https で 128.242.245.39 へ接続しているです。

ポート番号を直接指定する

以下のように -i:<ポート番号> オプションを使う:

$ lsof -i:23052
COMMAND    PID   USER   FD   TYPE     DEVICE SIZE/OFF NODE NAME
GrowlHelp 2197 yokada    9u  IPv4 0x0a4cb748      0t0  TCP *:23052 (LISTEN)