728x90

출처 : Android NDK FFmpeg 컴파일 강좌 (1/4)
Android NDK FFmpeg 컴파일 강좌 (4/4)
Android NDK FFmpeg 컴파일 강좌 (3/4)
Android NDK FFmpeg 컴파일 강좌 (2/4)
Android NDK FFmpeg 컴파일 강좌 (새로운 시도)
http://blog.daum.net/hopefullife/209
Android NDK Overview
Android NDK 빌드환경을 사용하지 않는 Makefile
Decoding audio via Android using FFMpeg
OpenMAX AL for ffmpeg
live-converter
read-only stream buffer interface in ffmpeg #1
FFmpeg port for Android ndk
android-ndk-r7 编译 ffmpeg-0.10
Android AudioRecord to FFMPEG encode native AAC
http://www.2cto.com/kf/201201/116171.html
http://pastebin.com/P02Fmw53
AndroidCompile

안드로이드펍에서 남은그루터기, 로봇시대 글을 보고, 컴파일 해보았는데, 작업해야될 부분이 많았어서,
인터넷에서 여러가지 글을 찾아보고, 간단하게 할 수 있는 방법을 찾아 보았습니다.

일주일 동안의 고생한 내용을 정리합니다. 안드로이드펍의 남은그루터기님과, 로봇시대님에게 감사한마음 글로나마 드립니다.

toolchain을 /opt/android-8-toolchain 설치하고, ffmpeg 폴더에 config.sh 파일을 아래와 같이 만들었습니다.
C 드라이브에 ffmpegtmp 폴더를 만들고, 남은그루터기님 처럼 configure 파일은 수정하지 않았습니다.

그리고, 남은그루터기님의 소스를 받아서 rtsp 주소로 실행하면 "Open Movie Error: -2" 라고 나오는데,
지원이 안되는 것으로 알고 있었는데, 프로젝트의 AndroidManifest.xml 파일에 인터넷 접근 권한을 추가 해야  되더군요.
2일이나 고생해서 찾았습니다.

config.sh 파일

export TMPDIR=c:/ffmpegtmp
export ANDROID_ROOT=/opt/android-8-toolchain

./configure --target-os=linux \
--arch=arm \
--enable-cross-compile \
--cc=$ANDROID_ROOT/bin/arm-linux-androideabi-gcc \
--cross-prefix=$ANDROID_ROOT/bin/arm-linux-androideabi- \
--extra-cflags="-marm -march=armv7-a -mfloat-abi=softfp -mfpu=neon" \
--extra-ldflags="-Wl,--fix-cortex-a8" \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-devices \
--disable-filters \
--disable-yasm \
--enable-network \
--enable-protocol=tcp \
--enable-demuxer=rtsp \
--enable-decoder=h264

남은그루터기님은 각라이브러리 폴더에 Android.mk을 만드셨지만,
config.sh 파일은 만들고 ./config.sh 실행하고 make 컴파일 실행하면,
각 라이브러리 폴더에 .a 파일로 파일이 생성됩니다.
jni 컴파일 할때도 이 라이브러리 파일만 참조 하시면 됩니다.

CPU별 --extra-cflags 추가 플래그

arm v6
    -marm -march=armv6

arm v7vfpv3
    -mfloat-abi=softfp -mfpu=vfpv3-d16 -marm -march=armv7-a

arm v7vfp
    -mfloat-abi=softfp -mfpu=vfp -marm -march=armv7-a

arm v7n
    -mfloat-abi=softfp -mfpu=neon -marm -march=armv7-a -mtune=cortex-a8

arm v6+vfp
    -DCMP_HAVE_VFP -mfloat-abi=softfp -mfpu=vfp -marm -march=armv6

컴파일

$ ./config.sh

$ make

BasicPlayer.c 수정 - 남은그루터기 소스 원본의 내용 일부

#include "avcodec.h"
#include "avformat.h"
#include "swscale.h"

수정된 소스

#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"

Application.mk

APP_ABI := armeabi armeabi-v7a
APP_PLATFORM := android-8

Android.mk

# 참조
#      http://berabue.tistory.com/67
#      http://www.newsmth.net/bbsanc.php?path=%2Fgroups%2Fcomp.faq%2FMobileDev%2Fandroid%2FM.1315568907.n0&ap=275

# 컴파일하고자 하는 소스파일 위치를 알려줍니다. Android.mk를 jni에 놔두었으니 프로젝트/jni폴더가 됩니다.
LOCAL_PATH := $(call my-dir)

FFMPEGDIR := D:/Windows/cygwin/home/bluesanta/BluePlayer/jni/ffmpeg

# LOCAL로 시작하는것들을 초기화시킨다고합니다. LOCAL_PATH는 제외.
include $(CLEAR_VARS)

LOCAL_C_INCLUDES := $(FFMPEGDIR)

# List 'cpufeatures' in your list of static library dependencies
LOCAL_STATIC_LIBRARIES := cpufeatures

# 생성될 so파일명입니다.
LOCAL_MODULE    := libbasicplayer

# 컴파일할 소스파일을 추가합니다.  
LOCAL_SRC_FILES := Interface.c BasicPlayer.c

LDFFMPEG = -L$(FFMPEGDIR)/libavformat -L$(FFMPEGDIR)/libavcodec -L$(FFMPEGDIR)/libavutil -L$(FFMPEGDIR)/libswscale
LOCAL_LDLIBS    := $(LDFFMPEG) -lavformat -lswscale -lavcodec -lavutil -lz -lm -llog -ljnigraphics

# 공유 라이브러리를 생성합니다.
include $(BUILD_SHARED_LIBRARY)

# At the end of your Android.mk, import the 'android/cpufeatures'
$(call import-module,android/cpufeatures)

컴파일

$ ndk-build

728x90
728x90

출처 : RTMPDump
Compiling RTMPdump on Max OS X
Compiling FFmpeg 0.9 with libRTMP and libmp3lame for Intel and ARM CPUs
Compiling FFMPEG 0.6 with RTMP Support for OSX
ffmpeg ndk 빌드 #2 ffmpeg 옵션별 빌드
best-video-player
Fix rtmp double cflags in pkgconfig module

다운로드

RTMPDump 에서 rtmpdump-2.3.tgz 파일 다운로드

압축풀기

$ tar xvfz rtmpdump-2.3.gz

ffmpeg 폴더로 이동 시키기

mv rtmpdump-2.3/librtmp ffmpeg-0.10.3

rtmp 라이브러리 컴파일, 설치

$ cd ffmpeg-0.10.3/librtmp
$ make SYS=linux install
$ echo 'export PKG_CONFIG_PATH=/lib/pkgconfig:/usr/local/lib/pkgconfig' | tee -a ~/.bashrc

configure

config.sh 파일

export TMPDIR=c:/ffmpegtmp

./configure --disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-devices \
--disable-filters \
--disable-yasm \
--enable-network \
--enable-protocol=tcp \
--enable-demuxer=rtsp \
--enable-decoder=h264 \
--enable-librtmp

$ ./config.sh

$ make

testmain.c

#include <stdio.h> 
#include <stdlib.h> 
#include <libavcodec/avcodec.h> 
#include <libavformat/avformat.h> 
#include <libavformat/avio.h> 
 
 
int main(int argc, char** argv) { 
 
    AVFormatContext* context = avformat_alloc_context(); 
    int video_stream_index; 
 
    av_register_all(); 
    avcodec_register_all(); 
    avformat_network_init(); 

    //if(avformat_open_input(&context, "rtsp://192.168.0.40/vod/mp4:sample.mp4",NULL,NULL) != 0){ 
  	//if(avformat_open_input(&context, "rtmp://192.168.0.40/vod/sample.mp4",NULL,NULL) != 0){     	
    //if(avformat_open_input(&context, "d:\\windows\\b.mp4",NULL,NULL) != 0){ 
 
    //open rtsp 
    if(avformat_open_input(&context, "rtmp://192.168.0.40/vod/sample.mp4",NULL,NULL) != 0){     	
        return EXIT_FAILURE; 
    } 
 
    if(avformat_find_stream_info(context,NULL) < 0){ 
        return EXIT_FAILURE; 
    } 
 
    //search video stream 
    int i;
    for(i =0;i<context->nb_streams;i++){ 
        if(context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
            video_stream_index = i; 
    } 
 
    AVPacket packet; 
    av_init_packet(&packet); 
 
    //open output file 
    AVOutputFormat* fmt = av_guess_format(NULL,"test2.avi",NULL); 
    AVFormatContext* oc = avformat_alloc_context(); 
    oc->oformat = fmt; 
    avio_open2(&oc->pb, "test.avi", AVIO_FLAG_WRITE,NULL,NULL); 
 
    AVStream* stream=NULL; 
    int cnt = 0; 
    //start reading packets from stream and write them to file 
 
    av_read_play(context);//play RTSP 
    while(av_read_frame(context,&packet)>=0 && cnt <100){//read 100 frames 
        if(packet.stream_index == video_stream_index){//packet is video                
            if(stream == NULL){//create stream in file 
                stream = avformat_new_stream(oc,context->streams[video_stream_index]->codec->codec); 
                avcodec_copy_context(stream->codec,context->streams[video_stream_index]->codec); 
                stream->sample_aspect_ratio = context->streams[video_stream_index]->codec->sample_aspect_ratio; 
                avformat_write_header(oc,NULL); 
            } 
            packet.stream_index = stream->id; 
 
            av_write_frame(oc,&packet); 
            cnt++; 
        } 
        av_free_packet(&packet); 
        av_init_packet(&packet); 
    } 
    av_read_pause(context); 
    av_write_trailer(oc); 
    avio_close(oc->pb); 
    avformat_free_context(oc); 
 
    return (EXIT_SUCCESS); 
} 

Makefile

TARGET = hello3

FFMPEGDIR = /home/bluesanta/ffmpeg-0.10.3

LIBDIR = /lib

CC 	= gcc
AR 	= ar
LD 	= ld
NM 	= nm
RANLIB 	= ranlib
STRIP = strip

INCLUDE = -I.. -I.

CFLAGS = -Wall
LDFFMPEG = -L$(FFMPEGDIR)/libavformat -L$(FFMPEGDIR)/libavcodec -L$(FFMPEGDIR)/libavutil -L$(FFMPEGDIR)/librtmp
LDFLAGS = -L$(LIBDIR) $(LDFFMPEG) -lavformat -lavcodec -lavutil -lrtmp -lkernel32 -lcygwin -lm -lgcc -lc -lssl -lz -lcrypto

# application file
APPSOURCES = testmain.c
APPOBJS = $(APPSOURCES:.c=.o)

# define the rule
.SUFFIXES:.c .o 

.c.o:
	@echo Compiling: $< 
	$(CC) -c $(CFLAGS)  $(INCLUDE) -o $@ $<

all: app

app: $(APPOBJS)
	@echo Linking: $(TARGET) 
	$(CC) -o $(TARGET) $(APPOBJS) $(LDFLAGS)
	$(STRIP) -s $(TARGET)

clean:
	@rm -vf $(APPOBJS) $(TARGET) 

컴파일, 실행

 

728x90
728x90

출처 : Record RTSP stream with FFmpeg libavformat
Android NDK FFmpeg 컴파일 강좌 (1/4)

환경

wowza 2.2.4, ffmpeg-0.10.3, cygwin, windows 7

압축풀기

$ tar xvfz ffmpeg-0.10.3.tar.gz

configure

config.sh 파일

export TMPDIR=c:/ffmpegtmp

./configure --disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-devices \
--disable-filters \
--disable-yasm \
--enable-network \
--enable-protocol=tcp \
--enable-demuxer=rtsp \
--enable-decoder=h264 

$ ./config.sh

$ make

testmain.c

#include <stdio.h> 
#include <stdlib.h> 
#include <libavcodec/avcodec.h> 
#include <libavformat/avformat.h> 
#include <libavformat/avio.h> 
 
 
int main(int argc, char** argv) { 
 
    AVFormatContext* context = avformat_alloc_context(); 
    int video_stream_index; 
 
    av_register_all(); 
    avcodec_register_all(); 
    avformat_network_init(); 

  	//if(avformat_open_input(&context, "rtmp://192.168.0.40/vod/sample.mp4",NULL,NULL) != 0){     	
    //if(avformat_open_input(&context, "d:\\windows\\b.mp4",NULL,NULL) != 0){ 
 
    //open rtsp 
    if(avformat_open_input(&context, "rtsp://192.168.0.40/vod/mp4:sample.mp4",NULL,NULL) != 0){ 
        return EXIT_FAILURE; 
    } 
 
    if(avformat_find_stream_info(context,NULL) < 0){ 
        return EXIT_FAILURE; 
    } 
 
    //search video stream 
    int i;
    for(i =0;i<context->nb_streams;i++){ 
        if(context->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) 
            video_stream_index = i; 
    } 
 
    AVPacket packet; 
    av_init_packet(&packet); 
 
    //open output file 
    AVOutputFormat* fmt = av_guess_format(NULL,"test2.avi",NULL); 
    AVFormatContext* oc = avformat_alloc_context(); 
    oc->oformat = fmt; 
    avio_open2(&oc->pb, "test.avi", AVIO_FLAG_WRITE,NULL,NULL); 
 
    AVStream* stream=NULL; 
    int cnt = 0; 
    //start reading packets from stream and write them to file 
 
    av_read_play(context);//play RTSP 
    while(av_read_frame(context,&packet)>=0 && cnt <100){//read 100 frames 
        if(packet.stream_index == video_stream_index){//packet is video                
            if(stream == NULL){//create stream in file 
                stream = avformat_new_stream(oc,context->streams[video_stream_index]->codec->codec); 
                avcodec_copy_context(stream->codec,context->streams[video_stream_index]->codec); 
                stream->sample_aspect_ratio = context->streams[video_stream_index]->codec->sample_aspect_ratio; 
                avformat_write_header(oc,NULL); 
            } 
            packet.stream_index = stream->id; 
 
            av_write_frame(oc,&packet); 
            cnt++; 
        } 
        av_free_packet(&packet); 
        av_init_packet(&packet); 
    } 
    av_read_pause(context); 
    av_write_trailer(oc); 
    avio_close(oc->pb); 
    avformat_free_context(oc); 
 
    return (EXIT_SUCCESS); 
} 

Makefile

TARGET = hello2

FFMPEGDIR = /home/bluesanta/ffmpeg-0.10.3

LIBDIR = /lib

CC 	= gcc
AR 	= ar
LD 	= ld
NM 	= nm
RANLIB 	= ranlib
STRIP = strip

INCLUDE = -I$(FFMPEGDIR)

CFLAGS = -Wall
LDFFMPEG = -L$(FFMPEGDIR)/libavformat -L$(FFMPEGDIR)/libavcodec -L$(FFMPEGDIR)/libavutil 
LDFLAGS = -L$(LIBDIR) $(LDFFMPEG) -lavformat -lavcodec -lavutil -lkernel32 -lcygwin -lm -lgcc -lc

# application file
APPSOURCES = testmain.c
APPOBJS = $(APPSOURCES:.c=.o)

# define the rule
.SUFFIXES:.c .o 

.c.o:
	@echo Compiling: $< 
	$(CC) -c $(CFLAGS)  $(INCLUDE) -o $@ $<

all: app

app: $(APPOBJS)
	@echo Linking: $(TARGET) 
	$(CC) -o $(TARGET) $(APPOBJS) $(LDFLAGS)
	$(STRIP) -s $(TARGET)

clean:
	@rm -vf $(APPOBJS) $(TARGET) 

컴파일, 실행

728x90
728x90

출처

main.c 파일

#include <stdio.h>

int main(int argc, char* argv[])
{
	printf("Hello Android NDK! \n");	

	return 0;
}

Makefile 파일

TARGET = hello

TOOLCHAIN = D:/Windows/cygwin/opt/android-8-toolchain

CROSS  = $(TOOLCHAIN)/bin/arm-linux-androideabi-
INCDIR = $(TOOLCHAIN)/sysroot/usr/include
LIBDIR = $(TOOLCHAIN)/sysroot/usr/lib

CC 	= $(CROSS)gcc
AR 	= $(CROSS)ar
LD 	= $(CROSS)ld
NM 	= $(CROSS)nm
RANLIB 	= $(CROSS)ranlib
STRIP = $(CROSS)strip

INCLUDE = -I. -I$(INCDIR) 

CFLAGS = -Wall
LDFLAGS = -nostdlib -Wl,--dynamic-linker,"//system/bin/linker" -L$(LIBDIR) -lc -lm -lstdc++ -ldl
#LDFLAGS = -static -lc -lm -lstdc++

# crt 
CRTOBJ = $(LIBDIR)/crtbegin_dynamic.o

# application file
APPSOURCES = main.c
APPOBJS = $(APPSOURCES:.c=.o)

# define the rule
.SUFFIXES:.c .o 

.c.o:
	@echo Compiling: $< 
	$(CC) -c $(CFLAGS)  $(INCLUDE) -o $@ $<

all: app

app: $(APPOBJS)
	@echo Linking: $(TARGET) 
	$(CC) -o $(TARGET) $(APPOBJS) $(CRTOBJ) $(LDFLAGS)
	$(STRIP) -s $(TARGET)

clean:
	@rm -vf $(APPOBJS) $(TARGET) 
	

테스트

 

728x90
728x90

출처 : http://inmist.tistory.com/entry/%EC%8A%A4%ED%81%AC%EB%9E%A9Android-NDK-%EC%82%AC%EC%9A%A9%EB%B2%95
http://www.kkaneko.com/rinkou/js/andk.html
http://darkryu.egloos.com/m/3299369

NDK 다운로드

http://developer.android.com/sdk/ndk/index.html

NDK 설치

cd 다운로드
tar xvjof android-ndk-r8-linux-x86.tar.bz2
mv android-ndk-r8 ~/dev

NDK 환경 설정

echo 'export ANDROID_NDK_ROOT=/home/user1/dev/android-ndk-r8' | tee -a ~/.bashrc
echo 'export ANDROID_SDK_ROOT=/home/user1/dev/android-sdks' | tee -a ~/.bashrc
echo 'export PATH=$PATH:$ANDROID_NDK_ROOT:$ANDROID_SDK_ROOT/tools:$ANDROID_SDK_ROOT/platform-tools' | tee -a ~/.bashrc

ToolChain 만들기

sudo ~/dev/android-ndk-r8/build/tools/make-standalone-toolchain.sh --ndk-dir=/home/user1/dev/android-ndk-r8 --platform=android-8 --install-dir=/opt/android-8-toolchain
sudo chown user1:user1 -hR /opt/android-8-toolchain

echo 'export TOOLCHAIN=/opt/android-8-toolchain' | tee -a ~/.bashrc
echo 'export PATH=$TOOLCHAIN/bin:$PATH' | tee -a ~/.bashrc
echo 'export CC=arm-linux-androideabi-gcc' | tee -a ~/.bashrc

cygwin (참조용)
./make-standalone-toolchain.sh --ndk-dir=/opt/android-ndk --platform=android-8 --install-dir=/opt/android-8-toolchain

NDK 테스트 빌드

cd ~/dev/android-ndk-r8/samples/hello-jni/jni
ndk-build

컴파일 확인

NDK Sample 만들기 

기본 Sample을 사용하는 것이라서 HelloJni 입력하고, [Next] 버튼 선택

Target SDK를 Android 2.1로 선택하고, [Next] 버튼 선택

Package Name : com.example.hellojni
Create Activity : HelloJni

HelloJni.java파일를 NDK Sample 폴더에서 복사하거나, 아래와 같이 입력 한다

package com.example.hellojni;

import android.app.Activity;
import android.widget.TextView;
import android.os.Bundle;


public class HelloJni extends Activity
{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);

        /** 
         * Create a TextView and set its content.
         * the text is retrieved by calling a native
         * function.
         */
        TextView  tv = new TextView(this);
        tv.setText( stringFromJNI() );
        setContentView(tv);
    }

    /**
     * A native method that is implemented by the
     * 'hello-jni' native library, which is packaged
     * with this application.
     */
    public native String  stringFromJNI();

    /**
     * This is another native method declaration that is *not*
     * implemented by 'hello-jni'. This is simply to show that
     * you can declare as many native methods in your Java code
     * as you want, their implementation is searched in the
     * currently loaded native libraries only the first time
     * you call them.
     *
     * Trying to call this function will result in a
     * java.lang.UnsatisfiedLinkError exception !
     */
    public native String  unimplementedStringFromJNI();

    /**
     * this is used to load the 'hello-jni' library on application
     * startup. The library has already been unpacked into
     * /data/data/com.example.HelloJni/lib/libhello-jni.so at
     * installation time by the package manager.
     */
    static {
        System.loadLibrary("hello-jni");
    }
}

jni 폴더를 만들고, Android.mk, hello-jni.c NDK Sample 폴더에서 복사하거나, 아래와 같이 입력 한다.

Android.mk 파일

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c

include $(BUILD_SHARED_LIBRARY)

hello-jni.c 파일

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

/* This is a trivial JNI example where we use a native method
 * to return a new VM String. See the corresponding Java source
 * file located at:
 *
 *   apps/samples/hello-jni/project/src/com/example/HelloJni/HelloJni.java
 */
jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                                  jobject thiz )
{
    return (*env)->NewStringUTF(env, "Hello from JNI !");
}

NDK 빌드

cd ~/dev/workspace/HelloJni/jni
ndk-build

HelloJni 프로젝트를 refresh 해보면 libs/armeabi/libhello-jni.so 파일이 생성 된것을 확인 할 수 있다. 

실행

728x90
728x90

QueryTool 실행해서 테이블 목록에서 테이블를 오른쪽 마우스를 선택해서 MyBatis Java Class 생성를 선택한다.

MyBatis Java Class 생성 선택

옵션 설정

MyBatis Java 패키지 경로 설정

게시판 정보 설정

테이블 타이블 : 게시판 이름으로 사용됨
Comment에 반경 버튼 : 테이블 타이틀에 작성한 내용을 선택한 테이블의 주석으로 반영(Database에 반영)
페이지 사이즈 : 게시판 리스트의 한 페이지당 개수
기본폴더 : Web 주소의 prefix

게시판 리스트 설정

View : 리스트에 출력되는 컬럼 선택
Mian : 리스트의 메인(타이틀이나 제목)이 되는 컬럼 선택
Column : 컬럼명
Title : 게시판 저장 화면에서 출력되는 타이블명
Title값 Comment에 반영 : 작성한 주석의 내용을 Database에 반영

게시판 저장 항목 선택

게시판에 저장할 컬럼을 선택한다.

OK 버튼을 선택하면 MyBatis 텝에 MyBastic 관련 Java 클래스와 xml 파일이 생성됨

 

domain 클래스(자동으로 생성된 코드)

package itg.retis.db.domain;

import java.sql.Date;
import java.sql.Timestamp;

import bluexmas.util.DateUtils;
import net.sf.json.JSONObject;

public class CodeType {

  // pk
  private String type_id;
  
  private String type_name;
  private String type_desc;
  private String is_lock;
  private String is_visible;
  
  public void setType_id(String type_id) {
    this.type_id = type_id;
  }
  public String getType_id() {
    return this.type_id;
  }
  public void setType_name(String type_name) {
    this.type_name = type_name;
  }
  public String getType_name() {
    return this.type_name;
  }
  public void setType_desc(String type_desc) {
    this.type_desc = type_desc;
  }
  public String getType_desc() {
    return this.type_desc;
  }
  public void setIs_lock(String is_lock) {
    this.is_lock = is_lock;
  }
  public String getIs_lock() {
    return this.is_lock;
  }
  public void setIs_visible(String is_visible) {
    this.is_visible = is_visible;
  }
  public String getIs_visible() {
    return this.is_visible;
  }
  public JSONObject getJSONObject() {
    JSONObject jobj = new JSONObject();
    jobj.put("type_id", this.type_id);
    jobj.put("type_name", this.type_name);
    jobj.put("type_desc", this.type_desc);
    jobj.put("is_lock", this.is_lock);
    jobj.put("is_visible", this.is_visible);
    return jobj;
  }
}

persistence 클래스(자동으로 생성된 코드)

package itg.retis.db.persistence;

import java.util.List;
import java.util.Map;

import itg.retis.db.domain.CodeType;

public interface CodeTypeMapper {

  public CodeType selectCodeType(Map<STRING, Object> params);

  public void insertCodeType(CodeType codeType);

  public void updateCodeType(CodeType codeType);

  public void deleteCodeType(Map<STRING, Object> params);

  public int getCount();

  public List<CODETYPE> listCodeType(Map<STRING, Integer> map);

}

service 클래스(자동으로 생성된 코드)

package itg.retis.db.service;

import itg.retis.db.domain.CodeType;
import itg.retis.db.persistence.CodeTypeMapper;

import java.util.HashMap;
import java.util.Map;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class CodeTypeService {

  public final static int pagerowcnt = 25;

  @Autowired
  private CodeTypeMapper codeTypeMapper;

  public CodeType selectCodeType(String typeId) {
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("type_id",typeId);
    return codeTypeMapper.selectCodeType(params);
  }

  public void insertCodeType(CodeType codeType) {
    codeTypeMapper.insertCodeType(codeType);
  }

  public void updateCodeType(CodeType codeType) {
    codeTypeMapper.updateCodeType(codeType);
  }

  public void deleteCodeType(String typeId) {
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("type_id",typeId);
    codeTypeMapper.deleteCodeType(params);
  }

  public int getCount() {
  	return codeTypeMapper.getCount();
  }

  public List<CodeType> listCodeType(int page) throws Exception {
  	Map<String, Integer> params = new HashMap<String, Integer>();
    params.put("page", page);
    params.put("pagerowcnt", pagerowcnt);
    return codeTypeMapper.listCodeType(params);
  }

}

MyBatis xml 파일(자동으로 생성된 코드)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="itg.retis.db.persistence.CodeTypeMapper">

  <!-- selectCodeType -->
  <select id="selectCodeType" parameterType="map" resultType="itg.retis.db.domain.CodeType">
    select type_id
           ,type_name
           ,type_desc
           ,is_lock
           ,is_visible
      from code_type
     where type_id = #{type_id}
  </select>

  <!-- updateCodeType -->
  <update id="updateCodeType" parameterType="itg.retis.db.domain.CodeType" statementType="PREPARED">
      update code_type
        <trim prefix="SET" suffixOverrides=",">
          <if test="type_name != null">type_name = #{type_name, jdbcType=VARCHAR} ,</if>
          <if test="type_desc != null">type_desc = #{type_desc, jdbcType=VARCHAR} ,</if>
          <if test="is_lock != null">is_lock = #{is_lock, jdbcType=VARCHAR} ,</if>
          <if test="is_visible != null">is_visible = #{is_visible, jdbcType=VARCHAR} ,</if>
        </trim>
     where type_id = #{type_id}
  </update>

  <!-- insertCodeType -->
  <insert id="insertCodeType" parameterType="itg.retis.db.domain.CodeType" statementType="PREPARED">
      insert into code_type(
        <trim suffixOverrides=",">
          <if test="type_id != null">type_id ,</if>
          <if test="type_name != null">type_name ,</if>
          <if test="type_desc != null">type_desc ,</if>
          <if test="is_lock != null">is_lock ,</if>
          <if test="is_visible != null">is_visible ,</if>
        </trim>
        ) values	(
        <trim suffixOverrides=",">
          <if test="type_id != null">#{type_id, jdbcType=VARCHAR} ,</if>
          <if test="type_name != null">#{type_name, jdbcType=VARCHAR} ,</if>
          <if test="type_desc != null">#{type_desc, jdbcType=VARCHAR} ,</if>
          <if test="is_lock != null">#{is_lock, jdbcType=VARCHAR} ,</if>
          <if test="is_visible != null">#{is_visible, jdbcType=VARCHAR} ,</if>
        </trim>
        )
  </insert>

  <!-- deleteCodeType -->
  <delete id="deleteCodeType" parameterType="map" statementType="PREPARED">
      delete from code_type
     where type_id = #{type_id}
  </delete>

  <!-- getCount -->
  <select id="getCount" resultType="int">
    select count(*)
      from code_type
  </select>

  <!-- listCodeType -->
  <select id="listCodeType" parameterType="map" resultType="itg.retis.db.domain.CodeType">
    select * 
      from ( select t1.*, ceil( rownum / #{pagerowcnt}) as page 
               from (select * 
                       from code_type
                      order by type_id
                    ) t1 
           ) 
     where page = #{page} 
  </select>

</mapper>

JSONData 클래스(자동으로 생성된 코드)

package itg.retis.db.json;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import itg.retis.db.domain.CodeType;
import itg.retis.db.service.CodeTypeService;
import itg.retis.util.BeanUtils;
import bluexmas.util.DateUtils;
import bluexmas.util.DataUtils;

public class JSONCodeType implements JSONData {

  private CodeTypeService service;

  @Override
  public JSONObject getJSON(HttpServletRequest request, HttpServletResponse response) {

    service = (CodeTypeService)BeanUtils.getBean("codeTypeService");

    String subcmd = request.getParameter("subcmd");
    JSONObject jobj_data = null;
    if (subcmd.equals("add")) {
      jobj_data = getAddData(request, response);
    } else if (subcmd.equals("edit")) {
      jobj_data = getEditData(request, response);
    } else if (subcmd.equals("list")) {
      jobj_data = getListData(request, response);
    } else if (subcmd.equals("info")) {
      jobj_data = getInfoData(request, response);
    }
    return jobj_data;
  }

  public JSONObject getAddData(HttpServletRequest request, HttpServletResponse response) {

    CodeType codeType = new CodeType();
    try {
      codeType.setType_id(request.getParameter("type_id"));
      codeType.setType_name(request.getParameter("type_name"));
      codeType.setType_desc(request.getParameter("type_desc"));
      codeType.setIs_lock(request.getParameter("is_lock"));
      codeType.setIs_visible(request.getParameter("is_visible"));
    } catch (Exception e) {
      System.out.println(e.toString());
    }

    String errStr = null;
    try {
      service.insertCodeType(codeType);
    } catch (Exception e) {
      e.printStackTrace();
      errStr = "error !!! " + e.toString(); // e.toString();
    }

    JSONObject jobj_list = new JSONObject();
    jobj_list.put("err", (errStr==null ? "" : errStr));

    JSONObject jobj_data = new JSONObject();
    jobj_data.put("success", (errStr==null ? true : false));
    jobj_data.put("data", jobj_list);

    return jobj_data;
  }

  public JSONObject getEditData(HttpServletRequest request, HttpServletResponse response) {

    CodeType codeType = new CodeType();
    try {
      codeType.setType_id(request.getParameter("type_id"));
      codeType.setType_name(request.getParameter("type_name"));
      codeType.setType_desc(request.getParameter("type_desc"));
      codeType.setIs_lock(request.getParameter("is_lock"));
      codeType.setIs_visible(request.getParameter("is_visible"));
    } catch (Exception e) {
      System.out.println(e.toString());
    }

    String errStr = null;
    try {
      service.updateCodeType(codeType);
    } catch (Exception e) {
      e.printStackTrace();
      errStr = "error !!! " + e.toString(); // e.toString();
    }

    JSONObject jobj_list = new JSONObject();
    jobj_list.put("err", (errStr==null ? "" : errStr));

    JSONObject jobj_data = new JSONObject();
    jobj_data.put("success", (errStr==null ? true : false));
    jobj_data.put("data", jobj_list);

    return jobj_data;
  }

  public JSONObject getListData(HttpServletRequest request, HttpServletResponse response) {

    int pagerowcnt = 20;
    int pageIndex = 1;
    try {
      pageIndex = Integer.parseInt(request.getParameter("pageIndex"));
    } catch (Exception e) {
      System.out.println(e.toString());
    }

    int rowCount = service.getCount();

    if (pageIndex<1) {
      pageIndex = 1;
    }

    JSONArray arrayObj = new JSONArray();

    List<CodeType> dataList = null;
    String errStr = null;
    try {
      dataList = service.listCodeType(pageIndex);
    } catch (Exception e) {
      e.printStackTrace();
      errStr = "조회오류 !!! 데이터베이스 접속정보를 확인해 보세요."; // e.toString();
    }

    if (dataList!=null) {
      for (int i=0; i<dataList.size(); i++) {
        CodeType codetype = dataList.get(i);
        arrayObj.add(codetype.getJSONObject());
      }
    }

    JSONObject jobj_list = new JSONObject();
    jobj_list.put("list", arrayObj);
    jobj_list.put("err", (errStr==null ? "" : errStr));

    JSONObject jobj_data = new JSONObject();
    jobj_data.put("success", (errStr==null ? true : false));
    if (dataList!=null) {
      jobj_data.put("currentPage", pageIndex);
      jobj_data.put("total", rowCount);
      jobj_data.put("pageSize", pagerowcnt);
    }
    jobj_data.put("data", jobj_list);

    return jobj_data;
  }

  // Info
  public JSONObject getInfoData(HttpServletRequest request, HttpServletResponse response) {

    // pk
    String type_id = null;
    try {
        type_id = request.getParameter("type_id");
    } catch (Exception e) {
      System.out.println(e.toString());
    }

    String errStr = null;
    CodeType infoObj = null;
    try {
      infoObj = service.selectCodeType(type_id);
    } catch (Exception e) {
      e.printStackTrace();
      errStr = "조회오류 !!! 데이터베이스 접속정보를 확인해 보세요."; // e.toString();
    }

    JSONObject jobj_list = new JSONObject();
    jobj_list.put("info", infoObj.getJSONObject());
    jobj_list.put("err", (errStr==null ? "" : errStr));

    JSONObject jobj_data = new JSONObject();
    jobj_data.put("success", (errStr==null ? true : false));
    jobj_data.put("data", jobj_list);

    return jobj_data;
  }
}

JSONFactory 클래스에 JSONData 클래스가 반환 되도록 코드 추가
(사용자가 코드 추가)

package itg.retis.db.json;

public class JSONFactory {
	
	public static JSONData getJSONData(String cmd) {
		
		System.out.println("JSONFactory = " + cmd);

		if (cmd.equals("CodeType")) {   // 1 <-- 여기 두줄 추가
			return new JSONCodeType();  // 2
		} else {
			return new JSONSample();	
		}
	}
}

json 서블릿 호출하여 json data가 올바르게 전달되는지 확인

Sencha 텝에서 게시판 JavaScript 확인

code_type_list.js 소스 (자동으로 생성된 코드)

Ext.ns("ns_code_type_list");

ns_code_type_list.init = function(){

    var dataList;
    var dataStore;
    var pagingToolbar;
    var writeToolbar;

    Ext.regModel('dataModel', {
        fields: ['type_id','type_name','type_desc','is_lock','is_visible']
    });

    dataStore = new Ext.data.Store({
        model: 'dataModel',
        jsonData: [ currentPage = 1 ],
        data: [ ]
    });

    dataList = new Ext.List({
        title: 'CodeType목록',
        store: dataStore,
        scroll: false, // <-- 여기 중요
        layout:'fit', // <-- 여기 중요
        blockRefresh:true,
        onItemDisclosure: {
            handler: function(record, btn, index) {
                //alert(record.get('no'));
                ns_code_type_write.init();
                ns_code_type_write.panel.getInfoData(record.get('type_id'));
                main.MainPanel.setActiveItem(ns_code_type_write.panel, "slide");
            }
        },
        itemTpl:'{type_id} / {type_name} / {type_desc} / {is_lock} / {is_visible}'
    });

    function setList(aJsonData) {
        dataStore = new Ext.data.Store({
            model : 'dataModel',
            data : aJsonData.data.list,
            clearOnPageLoad : true,
            jsonData : aJsonData,
            previousPage: function() {
            	this.jsonData.currentPage = this.jsonData.currentPage - 1;
            	ns_code_type_list.panel_list.getList();
            },
            nextPage: function() {
            	this.jsonData.currentPage = this.jsonData.currentPage + 1;
            	ns_code_type_list.panel_list.getList();
            },
            loadPage: function(page) {
            	this.jsonData.currentPage =  page;
            	ns_code_type_list.panel_list.getList();
        	}
        });
        pagingToolbar.store = dataStore;
        pagingToolbar.handleStoreLoadSH(dataStore, true);

        dataList.bindStore(dataStore);

        ns_code_type_list.panel_list.scroller.scrollTo({
            x: 0,
            y: 0
        });
    };

    pagingToolbar = new Ext.ux.touch.PagingToolbar({
        ui: "charcoal",
        store : dataStore
    });

    writeToolbar = new Ext.Toolbar({
    		ui: "charcoal",
        items: [
        	{ xtype: 'spacer' },
          { text: '등록',
            handler:function() {
              ns_code_type_write.init();
           	 main.MainPanel.setActiveItem(ns_code_type_write.panel, "slide");
          	 }
          }
        ]
    });

    //
    dataStore.on('load', pagingToolbar.handleStoreLoad, pagingToolbar);

    ns_code_type_list.panel_list = new Ext.Panel({
        useCurrentLocation: true,
        scroll:'vertical',
        cardSwitchAnimation:"cube",
        getList:function()
        {
            Ext.Ajax.request({
                url: 'json',
                params : {
                    cmd : 'CodeType',
                    subcmd : 'list',

                    pageIndex : dataStore.jsonData.currentPage
                },
                success: function(response, opts) {
                    //console.log(response.responseText);
                    var JsonData = JSON.parse(response.responseText);
                    //console.log(JsonData);
                    if(JsonData.data.err == "") {
                        setList(JsonData);
                    } else {
                        alert(JsonData.data.err);
                    }
                }
            });
        },
        items:
        [{
            xtype: 'fieldset',
            instructions: 'CodeType목록 입니다. ',
            defaults: {
                labelAlign: 'left'
            },
            items: [
            	dataList,
            	pagingToolbar,
            	writeToolbar
            ]
        }]
    });
}

code_type_write.js 소스 (자동으로 생성된 코드)

Ext.ns("ns_code_type_write");

ns_code_type_write.init = function() {

  var m_subcmd = 'add';
  var m_type_id = "";

  ns_code_type_write.panel = new Ext.form.FormPanel({
    scroll : 'vertical',
    standardSubmit : false,
    title : 'Guestbook',
    items : [{
      xtype : 'fieldset',
      id : 'code_type_form',
      title : '코드타입 등록',
      // instructions: 'Please complete the information.',
      defaults : {
        labelAlign : 'left',
        labelWidth : '120'
      },
      items : [
      {
        xtype : 'textfield',
        id : 'type_id',
        label : '타입아이디',
        useClearIcon : true
      }
      , {
        xtype : 'textfield',
        id : 'type_name',
        label : '타입명',
        useClearIcon : true
      }
      , {
        xtype : 'textfield',
        id : 'type_desc',
        label : '설명',
        useClearIcon : true
      }
      , {
        xtype : 'textfield',
        id : 'is_lock',
        label : '잠금여부',
        useClearIcon : true
      }
      , {
        xtype : 'textfield',
        id : 'is_visible',
        label : '보여짐여부',
        useClearIcon : true
      }
            ]
    },
    {
      layout : {
        type : 'hbox',
        pack : 'center'
      },
      flex : 2,
      style : 'margin: .5em;',
      items : [ {
        xtype : 'button',
        ui : 'decline-round',
        id : 'btnAdd',
        name : 'btnAdd',
        handler : function() {
          Ext.Ajax.request({
            url: 'json',
            params : {
              cmd : 'CodeType',
              subcmd : m_subcmd,

              type_id : Ext.getCmp("type_id").getValue(),
              type_name : Ext.getCmp("type_name").getValue(),
              type_desc : Ext.getCmp("type_desc").getValue(),
              is_lock : Ext.getCmp("is_lock").getValue(),
              is_visible : Ext.getCmp("is_visible").getValue(),
            },
            success : function(response, opts) {
              //console.log(Ext.getCmp("login.user_id"));
              //console.log(response.responseText + Ext.getCmp("login.user_id").value);
              var JsonData = JSON.parse(response.responseText);
              console.log(JsonData);
              if (JsonData.data.err == "") {
                if (JsonData.data.result == "N") {
                  alert(JsonData.data.err);
                } else {
                  alert('등록이 완료 되었습니다.');
                  ns_code_type_list.panel_list.getList();
                  main.MainPanel.setActiveItem(ns_code_type_list.panel_list, "slide");
                }
              } else {
                alert(JsonData.data.err);
              }
            }
          });
        },
        text : '작성완료'
      } ]
    }],

    getInfoData : function(aTYPE_ID) {
      Ext.getCmp("code_type_form").setTitle('코드타입 수정');
      Ext.getCmp("btnAdd").setText('정보수정');
      m_subcmd = "edit";
      // alert('no = ' + ano);
      m_TYPE_ID = aTYPE_ID;
      Ext.Ajax.request({
        url: 'json',
        params : {
          cmd : 'CodeType'
          ,subcmd : 'info'
          ,type_id : aTYPE_ID
        },
        success : function(response, opts) {
          //console.log(response.responseText);
          var JsonData = JSON.parse(response.responseText);
          //console.log(JsonData);
          if (JsonData.data.err == "") {
            Ext.getCmp("type_id").setValue(JsonData.data.info.type_id);
            Ext.getCmp("type_name").setValue(JsonData.data.info.type_name);
            Ext.getCmp("type_desc").setValue(JsonData.data.info.type_desc);
            Ext.getCmp("is_lock").setValue(JsonData.data.info.is_lock);
            Ext.getCmp("is_visible").setValue(JsonData.data.info.is_visible);
          } else {
            alert(JsonData.data.err);
          }
        }
      });
    }
  });
}

확인 - 리스트

 

확인 - 저장

확인 - 조회 및 수정

마무리  

이 툴을 만들 당시 Sencha 2가 나왔기 때문에 현재 버전은 Sencha 1 버전으로만 생성이 되네요.
시간이 된다면 Sencha2 지원과 json 데이터 호출 ajax 부분도 php로 구현하고 하고 싶네요.

php json 호출 템플릿을 제공 하실분이 있으면 언제든지 연락주세요.

728x90
728x90

출처

http://rainflys.tistory.com/84
http://www.borlandforum.com/impboard/impboard.dll?action=read&db=del_qna&no=3570
http://bloodguy.tistory.com/entry/Delphi-바탕화면-시작메뉴프로그램-등-특수-디렉토리-가져오기

현재 실행 폴더 구하기

runpath:=ExtractFilePath(Application.ExeName);

Memo 스크롤 마지막으로 이동

procedure TForm1.Memo1Change(Sender: TObject);
begin
  Memo1.Perform(EM_LINESCROLL, 0, Memo1.Lines.Count);
end;

Format

 format('%0.10d',[10])

시스템 폴더 조회

// 시작 메뉴\프로그램 (C:\Documents and Settings\USER_NAME\시작 메뉴\프로그램)
SHGetFolderPath(0, CSIDL_PROGRAMS, 0, 0, PathPrograms);   
 
// 바탕 화면 (C:\Documents and Settings\USER_NAME\바탕 화면)
SHGetFolderPath(0, CSIDL_DESKTOP, 0, 0, PathDesktop);
unit Winapi.ShlObj;

  CSIDL_DESKTOP                 = $0000;          // 바탕화명 <desktop>
  CSIDL_INTERNET                = $0001;          // Internet Explorer (icon on desktop)
  CSIDL_PROGRAMS                = $0002;          //  시작메뉴\프로그램 Start Menu\Programs
  CSIDL_CONTROLS                = $0003;          // My Computer\Control Panel
  CSIDL_PRINTERS                = $0004;          // My Computer\Printers
  CSIDL_PERSONAL                = $0005;          // My Documents
  CSIDL_FAVORITES               = $0006;          // <user name>\Favorites
  CSIDL_STARTUP                 = $0007;          // Start Menu\Programs\Startup
  CSIDL_RECENT                  = $0008;          // <user name>\Recent
  CSIDL_SENDTO                  = $0009;          // <user name>\SendTo
  CSIDL_BITBUCKET               = $000a;          // <desktop>\Recycle Bin
  CSIDL_STARTMENU               = $000b;          // <user name>\Start Menu
  CSIDL_MYDOCUMENTS             = CSIDL_PERSONAL; // Personal was just a silly name for My Documents
  CSIDL_MYMUSIC                 = $000d;          // "My Music" folder
  CSIDL_MYVIDEO                 = $000e;          // "My Videos" folder
  CSIDL_DESKTOPDIRECTORY        = $0010;          // <user name>\Desktop
  CSIDL_DRIVES                  = $0011;          // My Computer
  CSIDL_NETWORK                 = $0012;          // Network Neighborhood (My Network Places)
  CSIDL_NETHOOD                 = $0013;          // <user name>\nethood
  CSIDL_FONTS                   = $0014;          // windows\fonts
  CSIDL_TEMPLATES               = $0015;

  CSIDL_COMMON_STARTMENU        = $0016;          // All Users\Start Menu
  CSIDL_COMMON_PROGRAMS         = $0017;          // All Users\Start Menu\Programs
  CSIDL_COMMON_STARTUP          = $0018;          // All Users\Startup
  CSIDL_COMMON_DESKTOPDIRECTORY = $0019;          // All Users\Desktop
  CSIDL_APPDATA                 = $001a;          // <user name>\Application Data
  CSIDL_PRINTHOOD               = $001b;          // <user name>\PrintHood
  CSIDL_LOCAL_APPDATA           = $001c;          // <user name>\Local Settings\Applicaiton Data (non roaming)
  CSIDL_ALTSTARTUP              = $001d;          // non localized startup
  CSIDL_COMMON_ALTSTARTUP       = $001e;          // non localized common startup
  CSIDL_COMMON_FAVORITES        = $001f;
  CSIDL_INTERNET_CACHE          = $0020;
  CSIDL_COOKIES                 = $0021;
  CSIDL_HISTORY                 = $0022;
  CSIDL_COMMON_APPDATA          = $0023;          // All Users\Application Data
  CSIDL_WINDOWS                 = $0024;          // GetWindowsDirectory()
  CSIDL_SYSTEM                  = $0025;          // GetSystemDirectory()
  CSIDL_PROGRAM_FILES           = $0026;          // C:\Program Files
  CSIDL_MYPICTURES              = $0027;          // C:\Program Files\My Pictures
  CSIDL_PROFILE                 = $0028;          // USERPROFILE
  CSIDL_SYSTEMX86               = $0029;          // x86 system directory on RISC
  CSIDL_PROGRAM_FILESX86        = $002a;          // x86 C:\Program Files on RISC
  CSIDL_PROGRAM_FILES_COMMON    = $002b;          // C:\Program Files\Common
  CSIDL_PROGRAM_FILES_COMMONX86 = $002c;          // x86 Program Files\Common on RISC
  CSIDL_COMMON_TEMPLATES        = $002d;          // All Users\Templates
  CSIDL_COMMON_DOCUMENTS        = $002e;          // All Users\Documents
  CSIDL_COMMON_ADMINTOOLS       = $002f;          // All Users\Start Menu\Programs\Administrative Tools
  CSIDL_ADMINTOOLS              = $0030;          // <user name>\Start Menu\Programs\Administrative Tools
  CSIDL_CONNECTIONS             = $0031;          // Network and Dial-up Connections
  CSIDL_COMMON_MUSIC            = $0035;          // All Users\My Music
  CSIDL_COMMON_PICTURES         = $0036;          // All Users\My Pictures
  CSIDL_COMMON_VIDEO            = $0037;          // All Users\My Video
  CSIDL_RESOURCES               = $0038;          // Resource Direcotry
  CSIDL_RESOURCES_LOCALIZED     = $0039;          // Localized Resource Direcotry
  CSIDL_COMMON_OEM_LINKS        = $003a;          // Links to All Users OEM specific apps
  CSIDL_CDBURN_AREA             = $003b;          // USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning

  // unused                               0x003c
  CSIDL_COMPUTERSNEARME         = $003d;          // Computers Near Me (computered from Workgroup membership)
  CSIDL_FLAG_CREATE             = $8000;          // combine with CSIDL_ value to force folder creation in SHGetFolderPath()
  CSIDL_FLAG_DONT_VERIFY        = $4000;          // combine with CSIDL_ value to return an unverified folder path
  CSIDL_FLAG_DONT_UNEXPAND      = $2000;          // combine with CSIDL_ value to avoid unexpanding environment variables
  CSIDL_FLAG_NO_ALIAS           = $1000;          // combine with CSIDL_ value to insure non-alias versions of the pidl
  CSIDL_FLAG_PER_USER_INIT      = $0800;          // combine with CSIDL_ value to indicate per-user init (eg. upgrade)
  CSIDL_FLAG_MASK               = $FF00;          // mask for all possible flag values

파일 경로 얻어오기

path := ExtractFilePath(Application.exeName);

- end -

728x90
728x90

- Ext.Panel의 높이 구하기 : myPanel.container.getHeight()
- dockedItems 첫번째 아이템 타이틀 수정 : this.dockedItems.items[0].setTitle('타이틀수정');
- 오늘날짜구하기 : var currentDate = new Date();
- 문자형날짜값을 날짜형으로 : Date.parseDate(JsonData.data.info.start_date, 'c')
- items 찾기 : writeToolbar.items.get('btnAdd').enable(); / writeToolbar.getChildItemById('btnAdd').disable();
- store record 삭제 : employee_submenu.panel_submenu.getListBox().store.removeAt(2);
- xtype : 'selectfield' option 동적추가 : this.items.get("emp.join").items.get("role").store.add({ text : '슈퍼바이저', value : '01' });

- Ext.data.Store 데이터추가

dataStore = new Ext.data.Store({ // 생략 
dataStore.add({"id": global_user_com_id, "comment": Ext.getCmp("txtComment").getValue()});

- Sencha Ext.XTemplate 데이터 적용시 replace

itemTpl : new Ext.XTemplate(
    '<TPL for=".">',
        '<DIV class=gcomment>',
            '<DIV class=gcomment-title>',
                '<SPAN class=id>{regid}</SPAN><SPAN class=date>{regdate:date("Y년 m월 d일")}</SPAN>',
            '</DIV>', 
            '<DIV class=gcomment-content>',
                '<P>{comment:this.linkify}</P>', 
            '</DIV>', 
        '</DIV>',
    '</TPL>', 
    {
        linkify : function(value) {
            return value.replace(/\n/g, "<br />");
        }
    }
)

- Sencha Ext.XTemplate 데이터 적용시 데이터변환

itemTpl:new Ext.XTemplate(
    '<div class="tweet-bubble">',
        '<div class="tweet-content">',
            '<h1>{title}</h1>',
            '<span>일정 {sdate:this.toDate} ~ {edate:this.toDate}</span>',
        '</div>',
    '</div>',
    '<div class="ttttt">',
        '<p>{insert_date:date("Y년 m월 d일")}</p>',
    '</div>',
    {
        toDate: function(values) {
            return values.substr(0, 4) + '년 ' + values.substr(4, 2) + '월 ' + values.substr(6, 2) + '일';
        }
    }
),              
listeners: {
    selectionchange: function(sel, records) {
        if (records[0] !== undefined) {
            alert(records[0].data.id);
        }
    }
}

Ext.ux.Image

Ext.ux.Image = Ext.extend(Ext.Component, {

    url : Ext.BLANK_IMAGE_URL,  //for initial src value
    
    //cls : 'con_preview',
    
    scale : 1,
    
    style : 'text-align: center;',
    
	html: [
		'<img>'
	],

	initComponent: function() {
		Ext.ux.Image.superclass.initComponent.apply(this, arguments);
		
		this.on('afterrender', this.initViewer, this, {delay: 10, single: true});
		
		this.addEvents('load');
	},
	
	initViewer: function() {
		// retrieve DOM els
		this.imgEl = this.el.down('img');

		this.imgEl.setStyle({
			'-webkit-user-drag': 'none'
			,'-webkit-transform-origin': '0 0'
			,'visibility': 'hidden'
		});

		
		this.el.setStyle({
			//backgroundImage: 'url('+this.previewSrc+')',
			backgroundPosition: 'center center'
			,backgroundRepeat: 'no-repeat'
			,webkitBackgroundSize: 'contain'
		});

		// attach event listeners
		this.mon(this.imgEl, {
			scope: this
			,load: this.onLoad
			//,doubletap: this.onDoubleTap
			//,pinchstart: this.onImagePinchStart
			//,pinch: this.onImagePinch
			//,pinchend: this.onImagePinchEnd
		});


		// load image
		if(this.url) {
			this.setSrc(this.url);	
		}
	},
 

    onLoad: function() {
    	
		this.viewportWidth = this.viewportWidth || this.getWidth() || this.ownerCt.body.getWidth();
		this.viewportHeight = this.viewportHeight || this.getHeight() || this.ownerCt.body.getHeight();
			
		// grab image size
		this.imgWidth = this.imgEl.dom.width
		this.imgHeight = this.imgEl.dom.height;
				
		// calculate and apply initial scale to fit image to screen
		if(this.imgWidth > this.viewportWidth || this.imgHeight > this.viewportHeight)
			this.scale = this.baseScale = Math.min(this.viewportWidth/this.imgWidth, this.viewportHeight/this.imgHeight);
		else
			this.scale = this.baseScale = 1;
		
		// set initial translation to center
		this.translateX = this.translateBaseX = (this.viewportWidth - this.baseScale * this.imgWidth) / 2;
		this.translateY = this.translateBaseY = (this.viewportHeight - this.baseScale * this.imgHeight) / 2;
		
		// show image and remove mask
		this.imgEl.setStyle({ visibility: 'visible' });

		var baseWidth = Math.min(this.viewportWidth, 480);

		this.scale = baseWidth / this.imgWidth;			  					
		
		var boundWidth = this.imgWidth * this.scale;
		var boundHeight = this.imgHeight * this.scale;
		
		this.setHeight(boundHeight);
		
		this.imgEl.setStyle({
			width: boundWidth + 'px'
			,height: boundHeight + 'px'
		});

        this.fireEvent('load', this);
    },
 
    setSrc: function(url) {
    	if(this.imgEl)
			this.imgEl.dom.src = url;
		else
			this.url = url;
			
	},
    
    onStateChange : function(request) {
        if (request && request.xhr && request.xhr.readyState == 4) {
            this.clearTimeout(request);
            this.onComplete(request);
            this.cleanup(request);
        }
    }
});

Dispatching an event on image click in Sencha Touch

	var panel223 = new Ext.Panel({		
		bodyStyle: 'background-image:url(img/mobile_bg.png); background-repeat:repeat',
		scroll: false,
		html : 
			'<table class="duty_view" style="width:100%;padding-top: 9px;">' +
			'<tr><td align="center" style="padding-top: 9px;" colspan="2"><img src="'+common_url+'img/logo.png" width="100%"/></td></tr>' +
			'<tr><td class="txt2" align="center">' +
			'<a style="width:150px" class="large button blue" id="btnApt">APT</a></td><td class="txt2" align="center">'+
			'<a style="width:150px" class="large button blue" id="btnBuilding">Building</a></td></tr>' +			
			'</table>',
			listeners: {
				render: function(c, records){
					c.getEl().on('click', function(event, el){
						alert(el.id);
					}, c, {stopEvent: true});
	 			}
			}
	});


728x90

+ Recent posts